diff --git a/pkg/common/storage/database/mgo/msg.go b/pkg/common/storage/database/mgo/msg.go index a7291fcc8f..611ed11e61 100644 --- a/pkg/common/storage/database/mgo/msg.go +++ b/pkg/common/storage/database/mgo/msg.go @@ -1,3 +1,17 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package mgo import ( @@ -204,9 +218,47 @@ func (m *MsgMgo) GetMsgDocModelByIndex(ctx context.Context, conversationID strin if sort != 1 && sort != -1 { return nil, errs.ErrArgs.WrapMsg("mongo sort must be 1 or -1") } - opt := options.Find().SetLimit(1).SetSkip(index).SetSort(bson.M{"doc_id": sort}).SetLimit(1) - filter := bson.M{"doc_id": primitive.Regex{Pattern: fmt.Sprintf("^%s:", conversationID)}} - msgs, err := mongoutil.Find[*model.MsgDocModel](ctx, m.coll, filter, opt) + + // parepare pipeline + pipeline := mongo.Pipeline{ + {{ + "$match", bson.D{ + {"doc_id", bson.M{"$regex": fmt.Sprintf("^%s:", conversationID)}}, + }, + }}, + {{ + "$project", bson.M{ + "doc_id": 1, + "seqSuffix": bson.M{ // Create a new field to store the converted seqSuffix integer. + "$toInt": bson.M{ // $toInt expression + "$arrayElemAt": bson.A{ // $arrayElemAt requires an array as the first argument. + bson.M{"$split": []interface{}{"$doc_id", ":"}}, // $split expression + -1, // Indexing, to take the last element of the array. + }, + }, + }, + "msgs": 1, + }, + }}, + {{ + "$sort", bson.D{ // Sort by seqSuffix. + {"seqSuffix", sort}, + }, + }}, + } + + // If pagination is needed, logic can be added here to dynamically modify the pipeline. + if index > 0 { + pipeline = append(pipeline, bson.D{{ + "$skip", index, + }}) + } + pipeline = append(pipeline, bson.D{{ + "$limit", 1, // We only need one document. + }}) + + // Execute an aggregation query. + msgs, err := mongoutil.Aggregate[*model.MsgDocModel](ctx, m.coll, pipeline) if err != nil { return nil, err } diff --git a/pkg/common/storage/database/mgo/msg_test.go b/pkg/common/storage/database/mgo/msg_test.go new file mode 100644 index 0000000000..65b8f64683 --- /dev/null +++ b/pkg/common/storage/database/mgo/msg_test.go @@ -0,0 +1,72 @@ +// Copyright © 2023 OpenIM. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mgo + +import ( + "context" + "fmt" + "github.com/openimsdk/open-im-server/v3/pkg/common/config" + "github.com/openimsdk/open-im-server/v3/pkg/common/storage/database" + "github.com/openimsdk/tools/db/mongoutil" + "testing" +) + +func GetTestDriver(t *testing.T, ctx context.Context) (database.Msg, error) { + + var mongoConf config.Mongo + mongoConf.URI = "" + mongoConf.Address = []string{"192.168.3.212:37017"} + mongoConf.Database = "openIM_v3" + mongoConf.Username = "root" + mongoConf.Password = "openIM123" + mongoConf.MaxPoolSize = 100 + mongoConf.MaxRetry = 10 + + mgocli, err := mongoutil.NewMongoDB(ctx, mongoConf.Build()) + if err != nil { + t.Fatal("NewMongoDB failed: ", err) + return nil, err + } + mongoDB := mgocli.GetDB() + + err = mongoDB.Client().Ping(ctx, nil) + if err != nil { + t.Fatal("Ping failed: ", err) + return nil, err + } + + return NewMsgMongo(mongoDB) +} + +func TestMsgMgo_GetMsgDocModelByIndex(t *testing.T) { + ctx := context.Background() + + driver, _ := GetTestDriver(t, ctx) + + conversationID := "si_10043_10070" + msg, err := driver.GetMsgDocModelByIndex(ctx, conversationID, 0, 1) + if err != nil { + t.Fatal("GetMsgDocModelByIndex failed: ", err) + } + + fmt.Println("GetMsgDocModelByIndex Ascent(1): ", msg.DocID) + + msg2, err := driver.GetMsgDocModelByIndex(ctx, conversationID, 0, -1) + if err != nil { + t.Fatal("GetMsgDocModelByIndex failed: ", err) + } + + fmt.Println("GetMsgDocModelByIndex Descent(-1): ", msg2.DocID) +}