Skip to content

Commit 7196301

Browse files
authored
feat: searchLocalMessages by SenderUserID. (#739)
* feat: searchLocalMessages by SenderUserID. * update wasm db interface and fix error. * add searchBykeyword logic. * update wasm para. * update logic. * feat: improve method implement. * update logic. * try empty * update sql query space.
1 parent c858b54 commit 7196301

File tree

7 files changed

+143
-91
lines changed

7 files changed

+143
-91
lines changed

internal/conversation_msg/conversation.go

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -337,9 +337,13 @@ func (c *Conversation) searchLocalMessages(ctx context.Context, searchParam *sdk
337337
if err != nil {
338338
return nil, err
339339
}
340+
340341
// Search by content type or keyword based on provided parameters
341342
if len(searchParam.MessageTypeList) != 0 && len(searchParam.KeywordList) == 0 {
342-
list, err = c.db.SearchMessageByContentType(ctx, searchParam.MessageTypeList, searchParam.ConversationID, startTime, endTime, offset, searchParam.Count)
343+
list, err = c.db.SearchMessageByContentType(ctx, searchParam.MessageTypeList, searchParam.SenderUserIDList, searchParam.ConversationID, startTime, endTime, offset, searchParam.Count)
344+
if err != nil {
345+
return nil, err
346+
}
343347
} else {
344348
newContentTypeList := func(list []int) (result []int) {
345349
for _, v := range list {
@@ -349,18 +353,24 @@ func (c *Conversation) searchLocalMessages(ctx context.Context, searchParam *sdk
349353
}
350354
return result
351355
}(searchParam.MessageTypeList)
356+
352357
if len(newContentTypeList) == 0 {
353358
newContentTypeList = SearchContentType
354359
}
355-
list, err = c.db.SearchMessageByKeyword(ctx, newContentTypeList, searchParam.KeywordList, searchParam.KeywordListMatchType,
356-
searchParam.ConversationID, startTime, endTime, offset, searchParam.Count)
360+
361+
list, err = c.db.SearchMessageByKeyword(ctx, newContentTypeList, searchParam.SenderUserIDList, searchParam.KeywordList,
362+
searchParam.KeywordListMatchType, searchParam.ConversationID, startTime, endTime, offset, searchParam.Count)
363+
if err != nil {
364+
return nil, err
365+
}
357366
}
358367
} else {
359368
// Comprehensive search across all conversations
360369
if len(searchParam.MessageTypeList) == 0 {
361370
searchParam.MessageTypeList = SearchContentType
362371
}
363-
list, err = c.searchMessageByContentTypeAndKeyword(ctx, searchParam.MessageTypeList, searchParam.KeywordList, searchParam.KeywordListMatchType, startTime, endTime)
372+
373+
list, err = c.searchMessageByContentTypeAndKeyword(ctx, searchParam.MessageTypeList, searchParam.SenderUserIDList, searchParam.KeywordList, searchParam.KeywordListMatchType, startTime, endTime)
364374
}
365375

366376
// Handle any errors encountered during the search
@@ -377,7 +387,7 @@ func (c *Conversation) searchLocalMessages(ctx context.Context, searchParam *sdk
377387
//log.Debug("hahh",utils.KMP("SSSsdf3434","F3434"))
378388
//log.Debug("hahh",utils.KMP("SSSsdf3434","SDF3"))
379389
// log.Debug("", "get raw data length is", len(list))
380-
log.ZDebug(ctx, "get raw data length is", len(list))
390+
log.ZDebug(ctx, "get raw data length is", "len", len(list))
381391

382392
for _, v := range list {
383393
temp := sdk_struct.MsgStruct{}
@@ -465,21 +475,23 @@ func (c *Conversation) searchLocalMessages(ctx context.Context, searchParam *sdk
465475
return &r, nil // Return the final search results
466476
}
467477

468-
func (c *Conversation) searchMessageByContentTypeAndKeyword(ctx context.Context, contentType []int, keywordList []string,
478+
func (c *Conversation) searchMessageByContentTypeAndKeyword(ctx context.Context, contentType []int, senderUserIDList []string, keywordList []string,
469479
keywordListMatchType int, startTime, endTime int64) (result []*model_struct.LocalChatLog, err error) {
470480
var list []*model_struct.LocalChatLog
481+
471482
conversationIDList, err := c.db.GetAllConversationIDList(ctx)
472483
if err != nil {
473484
return nil, err
474485
}
475486

476487
var mu sync.Mutex
477-
g, _ := errgroup.WithContext(ctx)
478-
g.SetLimit(searchMessageGoroutineLimit)
479-
for _, v := range conversationIDList {
480-
conversationID := v
481-
g.Go(func() error {
482-
sList, err := c.db.SearchMessageByContentTypeAndKeyword(ctx, contentType, conversationID, keywordList, keywordListMatchType, startTime, endTime)
488+
eg, _ := errgroup.WithContext(ctx)
489+
eg.SetLimit(searchMessageGoroutineLimit)
490+
for _, cID := range conversationIDList {
491+
conversationID := cID
492+
493+
eg.Go(func() error {
494+
sList, err := c.db.SearchMessageByContentTypeAndKeyword(ctx, contentType, conversationID, senderUserIDList, keywordList, keywordListMatchType, startTime, endTime)
483495
if err != nil {
484496
log.ZWarn(ctx, "search conversation message", err, "conversationID", conversationID)
485497
return nil
@@ -488,11 +500,12 @@ func (c *Conversation) searchMessageByContentTypeAndKeyword(ctx context.Context,
488500
mu.Lock()
489501
list = append(list, sList...)
490502
mu.Unlock()
503+
491504
return nil
492505
})
493506
}
494507

495-
if err := g.Wait(); err != nil {
508+
if err := eg.Wait(); err != nil {
496509
return nil, err
497510
}
498511

internal/conversation_msg/conversation_msg.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ import (
4444

4545
const (
4646
conversationSyncLimit int64 = math.MaxInt64
47-
searchMessageGoroutineLimit = 10
47+
searchMessageGoroutineLimit int = 10
4848
)
4949

5050
var SearchContentType = []int{constant.Text, constant.AtText, constant.File}

pkg/db/chat_log_model.go

Lines changed: 85 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"context"
2222
"errors"
2323
"fmt"
24+
"strings"
2425

2526
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
2627
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
@@ -221,88 +222,124 @@ func (d *DataBase) DeleteConversationMsgsBySeqs(ctx context.Context, conversatio
221222
return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("seq IN ?", seqs).Delete(model_struct.LocalChatLog{}).Error, "DeleteConversationMsgs failed")
222223
}
223224

224-
func (d *DataBase) SearchMessageByContentType(ctx context.Context, contentType []int, conversationID string, startTime, endTime int64, offset, count int) (result []*model_struct.LocalChatLog, err error) {
225+
func (d *DataBase) SearchMessageByContentType(ctx context.Context, contentType []int, senderUserIDList []string, conversationID string, startTime, endTime int64, offset, count int) (result []*model_struct.LocalChatLog, err error) {
225226
d.mRWMutex.RLock()
226227
defer d.mRWMutex.RUnlock()
227-
condition := fmt.Sprintf("send_time between %d and %d AND status <=%d And content_type IN ?", startTime, endTime, constant.MsgStatusSendFailed)
228-
err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where(condition, contentType).Order("send_time DESC").Offset(offset).Limit(count).Find(&result).Error, "SearchMessage failed")
228+
229+
var condition strings.Builder
230+
var args []interface{}
231+
232+
condition.WriteString("send_time between ? AND ? AND status <= ? AND content_type IN (?) ")
233+
args = append(args, startTime, endTime, constant.MsgStatusSendFailed, contentType)
234+
235+
if len(senderUserIDList) != 0 {
236+
condition.WriteString(" And send_id IN (?)")
237+
args = append(args, senderUserIDList)
238+
}
239+
240+
err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where(condition.String(), args...).Order("send_time DESC").Offset(offset).Limit(count).Find(&result).Error, "SearchMessage failed")
229241
return result, err
230242
}
231-
func (d *DataBase) SearchMessageByKeyword(ctx context.Context, contentType []int, keywordList []string, keywordListMatchType int, conversationID string, startTime, endTime int64, offset, count int) (result []*model_struct.LocalChatLog, err error) {
243+
244+
func (d *DataBase) SearchMessageByKeyword(ctx context.Context, contentType []int, senderUserIDList []string, keywordList []string, keywordListMatchType int, conversationID string, startTime, endTime int64, offset, count int) (result []*model_struct.LocalChatLog, err error) {
232245
d.mRWMutex.RLock()
233246
defer d.mRWMutex.RUnlock()
234-
var condition string
235-
var subCondition string
247+
248+
var condition strings.Builder
249+
var subCondition strings.Builder
250+
var args []interface{}
251+
252+
condition.WriteString(" send_time between ? AND ? AND status <= ? AND content_type IN (?)")
253+
args = append(args, startTime, endTime, constant.MsgStatusSendFailed, contentType)
254+
255+
// Construct a sub-condition for SQL query based on keyword list and match type
236256
if keywordListMatchType == constant.KeywordMatchOr {
237-
for i := 0; i < len(keywordList); i++ {
238-
if i == 0 {
239-
subCondition += "And ("
257+
// Use OR logic if keywordListMatchType is KeywordMatchOr
258+
subCondition.WriteString(" AND (")
259+
for i, keyword := range keywordList {
260+
if i > 0 {
261+
subCondition.WriteString(" OR ")
240262
}
241-
if i+1 >= len(keywordList) {
242-
subCondition += "content like " + "'%" + keywordList[i] + "%') "
243-
} else {
244-
subCondition += "content like " + "'%" + keywordList[i] + "%' " + "or "
245263

246-
}
264+
subCondition.WriteString("content LIKE ?")
265+
args = append(args, "%"+keyword+"%")
247266
}
267+
subCondition.WriteString(") ")
248268
} else {
249-
for i := 0; i < len(keywordList); i++ {
250-
if i == 0 {
251-
subCondition += "And ("
252-
}
253-
if i+1 >= len(keywordList) {
254-
subCondition += "content like " + "'%" + keywordList[i] + "%') "
255-
} else {
256-
subCondition += "content like " + "'%" + keywordList[i] + "%' " + "and "
269+
// Use AND logic for other keywordListMatchType
270+
subCondition.WriteString(" AND (")
271+
for i, keyword := range keywordList {
272+
if i > 0 {
273+
subCondition.WriteString(" AND ")
257274
}
275+
276+
subCondition.WriteString("content LIKE ?")
277+
args = append(args, "%"+keyword+"%")
258278
}
279+
subCondition.WriteString(") ")
259280
}
260-
condition = fmt.Sprintf(" send_time between %d and %d AND status <=%d And content_type IN ? ", startTime, endTime, constant.MsgStatusSendFailed)
261-
condition += subCondition
262-
err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where(condition, contentType).Order("send_time DESC").Offset(offset).Limit(count).Find(&result).Error, "SearchMessage failed")
281+
282+
condition.WriteString(subCondition.String())
283+
284+
if senderUserIDList != nil {
285+
condition.WriteString(" And send_id IN (?)")
286+
args = append(args, senderUserIDList)
287+
}
288+
289+
err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where(condition.String(), args...).Order("send_time DESC").Offset(offset).Limit(count).Find(&result).Error, "SearchMessage failed")
290+
263291
return result, err
264292
}
265293

266294
// SearchMessageByContentTypeAndKeyword searches for messages in the database that match specified content types and keywords within a given time range.
267-
func (d *DataBase) SearchMessageByContentTypeAndKeyword(ctx context.Context, contentType []int, conversationID string, keywordList []string, keywordListMatchType int, startTime, endTime int64) (result []*model_struct.LocalChatLog, err error) {
295+
func (d *DataBase) SearchMessageByContentTypeAndKeyword(ctx context.Context, contentType []int, conversationID string, senderUserIDList []string, keywordList []string, keywordListMatchType int, startTime, endTime int64) (result []*model_struct.LocalChatLog, err error) {
268296
d.mRWMutex.RLock()
269297
defer d.mRWMutex.RUnlock()
270-
var condition string
271-
var subCondition string
298+
299+
var condition strings.Builder
300+
var subCondition strings.Builder
301+
var args []interface{}
302+
303+
// Construct the main SQL condition string
304+
condition.WriteString(" send_time between ? AND ? AND status <= ? AND content_type IN (?)")
305+
args = append(args, startTime, endTime, constant.MsgStatusSendFailed, contentType)
272306

273307
// Construct a sub-condition for SQL query based on keyword list and match type
274308
if keywordListMatchType == constant.KeywordMatchOr {
275309
// Use OR logic if keywordListMatchType is KeywordMatchOr
276-
for i := 0; i < len(keywordList); i++ {
277-
if i == 0 {
278-
subCondition += "And ("
279-
}
280-
if i+1 >= len(keywordList) {
281-
subCondition += "content like " + "'%" + keywordList[i] + "%') "
282-
} else {
283-
subCondition += "content like " + "'%" + keywordList[i] + "%' " + "or "
310+
subCondition.WriteString(" AND (")
311+
for i, keyword := range keywordList {
312+
if i > 0 {
313+
subCondition.WriteString(" OR ")
284314
}
315+
316+
subCondition.WriteString("content LIKE ?")
317+
args = append(args, "%"+keyword+"%")
285318
}
319+
subCondition.WriteString(") ")
286320
} else {
287321
// Use AND logic for other keywordListMatchType
288-
for i := 0; i < len(keywordList); i++ {
289-
if i == 0 {
290-
subCondition += "And ("
291-
}
292-
if i+1 >= len(keywordList) {
293-
subCondition += "content like " + "'%" + keywordList[i] + "%') "
294-
} else {
295-
subCondition += "content like " + "'%" + keywordList[i] + "%' " + "and "
322+
subCondition.WriteString(" AND (")
323+
for i, keyword := range keywordList {
324+
if i > 0 {
325+
subCondition.WriteString(" AND ")
296326
}
327+
328+
subCondition.WriteString("content LIKE ?")
329+
args = append(args, "%"+keyword+"%")
297330
}
331+
subCondition.WriteString(") ")
298332
}
299333

300-
// Construct the main SQL condition string
301-
condition = fmt.Sprintf("send_time between %d and %d AND status <=%d And content_type IN ? ", startTime, endTime, constant.MsgStatusSendFailed)
302-
condition += subCondition
334+
condition.WriteString(subCondition.String())
335+
336+
if senderUserIDList != nil {
337+
condition.WriteString(" And send_id IN (?)")
338+
args = append(args, senderUserIDList)
339+
}
303340

304341
// Execute the query using the constructed condition and handle errors
305-
err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where(condition, contentType).Order("send_time DESC").Find(&result).Error, "SearchMessage failed")
342+
err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where(condition.String(), args...).Order("send_time DESC").Find(&result).Error, "SearchMessage failed")
306343

307344
return result, err
308345
}

pkg/db/db_interface/databse.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ type GroupModel interface {
5858
type MessageModel interface {
5959
BatchInsertMessageList(ctx context.Context, conversationID string, MessageList []*model_struct.LocalChatLog) error
6060
InsertMessage(ctx context.Context, conversationID string, Message *model_struct.LocalChatLog) error
61-
SearchMessageByKeyword(ctx context.Context, contentType []int, keywordList []string, keywordListMatchType int, conversationID string, startTime, endTime int64, offset, count int) (result []*model_struct.LocalChatLog, err error)
62-
SearchMessageByContentType(ctx context.Context, contentType []int, conversationID string, startTime, endTime int64, offset, count int) (result []*model_struct.LocalChatLog, err error)
63-
SearchMessageByContentTypeAndKeyword(ctx context.Context, contentType []int, conversationID string, keywordList []string, keywordListMatchType int, startTime, endTime int64) (result []*model_struct.LocalChatLog, err error)
61+
SearchMessageByKeyword(ctx context.Context, contentType []int, senderUserIDList []string, keywordList []string, keywordListMatchType int, conversationID string, startTime, endTime int64, offset, count int) (result []*model_struct.LocalChatLog, err error)
62+
SearchMessageByContentType(ctx context.Context, contentType []int, senderUserIDList []string, conversationID string, startTime, endTime int64, offset, count int) (result []*model_struct.LocalChatLog, err error)
63+
SearchMessageByContentTypeAndKeyword(ctx context.Context, contentType []int, conversationID string, senderUserIDList []string, keywordList []string, keywordListMatchType int, startTime, endTime int64) (result []*model_struct.LocalChatLog, err error)
6464
GetMessage(ctx context.Context, conversationID, clientMsgID string) (*model_struct.LocalChatLog, error)
6565
GetMessageBySeq(ctx context.Context, conversationID string, seq int64) (*model_struct.LocalChatLog, error)
6666
UpdateColumnsMessage(ctx context.Context, conversationID string, ClientMsgID string, args map[string]interface{}) error

test/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import "github.com/openimsdk/protocol/constant"
1919
const (
2020
APIADDR = "http://127.0.0.1:10002"
2121
WSADDR = "ws://127.0.0.1:10001"
22+
2223
UserID = "2237746339"
2324
)
2425

test/conversation_test.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,23 @@ func Test_InsertGroupMessageToLocalStorage(t *testing.T) {
165165
}
166166

167167
func Test_SearchLocalMessages(t *testing.T) {
168+
// req := &sdk_params_callback.SearchLocalMessagesParams{
169+
// Count: 20,
170+
// KeywordList: []string{"1"},
171+
// MessageTypeList: []int{105},
172+
// PageIndex: 1,
173+
// SenderUserIDList: []string{},
174+
// }
175+
168176
req := &sdk_params_callback.SearchLocalMessagesParams{
169-
Count: 20,
170177
KeywordList: []string{"1"},
178+
ConversationID: "sg_3161900504",
171179
MessageTypeList: []int{105},
172180
PageIndex: 1,
173-
SenderUserIDList: []string{},
181+
Count: 20,
182+
SenderUserIDList: []string{"1695766238"},
174183
}
184+
175185
msgs, err := open_im_sdk.UserForSDK.Conversation().SearchLocalMessages(ctx, req)
176186
if err != nil {
177187
t.Fatal(err)

0 commit comments

Comments
 (0)