package mongo import ( "context" "fmt" "time" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/stores/mon" "go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo/options" "go.mongodb.org/mongo-driver/v2/mongo/readpref" ) type DocumentDB struct { Mon *mon.Model } func NewDocumentDB(config *Conf, collection string, opts ...mon.Option) (DocumentDBUseCase, error) { if config == nil { return nil, fmt.Errorf("mongo: config is nil") } if collection == "" { return nil, fmt.Errorf("mongo: collection is required") } connectionURI, err := buildConnectionURI(*config) if err != nil { return nil, err } opts = append(opts, InitMongoOptions(*config)) logx.Infof("[DocumentDB] connecting to %s db=%s coll=%s", redactConnectionURI(connectionURI), config.Database, collection) client, err := mon.NewModel(connectionURI, config.Database, collection, opts...) if err != nil { return nil, fmt.Errorf("mongo: new model: %w", err) } timeout := time.Duration(config.ConnectTimeoutMs) * time.Millisecond if timeout <= 0 { timeout = 10 * time.Second } ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() if err := client.Collection.Database().Client().Ping(ctx, readpref.Primary()); err != nil { return nil, fmt.Errorf("mongo: ping primary: %w", err) } logx.Infof("[DocumentDB] connected") return &DocumentDB{Mon: client}, nil } func (document *DocumentDB) PopulateIndex(ctx context.Context, key string, sort int32, unique bool) error { return document.createIndex(ctx, []string{key}, []int32{sort}, unique, nil) } func (document *DocumentDB) PopulateTTLIndex(ctx context.Context, key string, sort int32, unique bool, ttl int32) error { return document.createIndex(ctx, []string{key}, []int32{sort}, unique, options.Index().SetExpireAfterSeconds(ttl)) } func (document *DocumentDB) PopulateMultiIndex(ctx context.Context, keys []string, sorts []int32, unique bool) error { if len(keys) != len(sorts) { return fmt.Errorf("mongo: keys and sorts length mismatch") } return document.createIndex(ctx, keys, sorts, unique, nil) } func (document *DocumentDB) createIndex( ctx context.Context, keys []string, sorts []int32, unique bool, indexOpt *options.IndexOptionsBuilder, ) error { c := document.Mon.Collection index := yieldIndexModel(keys, sorts, unique, indexOpt) ctx, cancel := context.WithTimeout(ctx, 3*time.Second) defer cancel() _, err := c.Indexes().CreateOne(ctx, index) if err != nil { return fmt.Errorf("mongo: create index: %w", err) } return nil } func (document *DocumentDB) GetClient() *mon.Model { return document.Mon } func yieldIndexModel(keys []string, sorts []int32, unique bool, indexOpt *options.IndexOptionsBuilder) mongo.IndexModel { setKeysDoc := bson.D{} for i, key := range keys { setKeysDoc = append(setKeysDoc, bson.E{Key: key, Value: sorts[i]}) } if indexOpt == nil { indexOpt = options.Index() } indexOpt.SetUnique(unique) return mongo.IndexModel{ Keys: setKeysDoc, Options: indexOpt, } }