package mdbc import ( "context" "fmt" "gitter.top/common/goref" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo/options" ) type findScope struct { scope *scope mdbc *mdbc ctx context.Context opts any limit *int64 skip *int64 upsert *bool sort bson.D filter any selects any doc any } func (fs *findScope) SetContext(ctx context.Context) *findScope { fs.ctx = ctx return fs } func (fs *findScope) SetFilter(filter any) *findScope { if filter == nil { fs.filter = bson.M{} return fs } fs.filter = filter return fs } func (fs *findScope) SetFindOptions(opts options.FindOptions) *findScope { fs.opts = &opts return fs } func (fs *findScope) SetFindOneOptions(opts options.FindOneOptions) *findScope { fs.opts = &opts return fs } func (fs *findScope) SetFindOneAndDeleteOptions(opts options.FindOneAndDeleteOptions) *findScope { fs.opts = &opts return fs } func (fs *findScope) SetFindOneAndUpdateOptions(opts options.FindOneAndUpdateOptions) *findScope { fs.opts = &opts return fs } func (fs *findScope) SetFindOneAndReplaceOptions(opts options.FindOneAndReplaceOptions) *findScope { fs.opts = &opts return fs } func (fs *findScope) SetLimit(limit int64) *findScope { fs.limit = &limit return fs } func (fs *findScope) SetSkip(skip int64) *findScope { fs.skip = &skip return fs } func (fs *findScope) SetUpsert(upsert bool) *findScope { fs.upsert = &upsert return fs } // SetSelects select field, such as: {key: 1, key: 0} // 1: display 0: hidden func (fs *findScope) SetSelects(selects any) *findScope { if !goref.IsBaseMap(selects) { return fs } fs.selects = selects return fs } func (fs *findScope) SetSort(sort bson.D) *findScope { fs.sort = sort return fs } func (fs *findScope) findMergeOptions() { if fs.ctx == nil { fs.ctx = context.Background() } if fs.filter == nil { fs.filter = bson.M{} } if fs.opts == nil { fs.opts = new(options.FindOptions) } opts := fs.opts.(*options.FindOptions) if fs.limit != nil { opts.Limit = fs.limit } if fs.skip == nil { opts.Skip = fs.skip } if fs.sort != nil { opts.Sort = fs.sort } if fs.selects != nil { opts.Projection = fs.selects } fs.opts = opts } // GetList get record list, list type is *[]*struct func (fs *findScope) GetList(list any) error { if !goref.IsBaseList(list) { return fmt.Errorf("invalid list type, must be *[]*struct") } fs.findMergeOptions() cursor, err := fs.mdbc.database.Collection(fs.scope.tableName).Find(fs.ctx, fs.filter, fs.opts.(*options.FindOptions)) if err != nil { return err } err = cursor.All(fs.ctx, list) if err != nil { return err } return nil } // GetMap get record map, m type is *map[string]*struct, field is struct field func (fs *findScope) GetMap(m any, field string) error { if !goref.IsBaseMap(m) { return fmt.Errorf("invalid m type, must be based on map") } fs.findMergeOptions() cursor, err := fs.mdbc.database.Collection(fs.scope.tableName).Find(fs.ctx, fs.filter, fs.opts.(*options.FindOptions)) if err != nil { return err } list := goref.BuildSlice(fs.scope.modelKind) err = cursor.All(fs.ctx, list) if err != nil { return err } if err := goref.SliceStructToMap(list, m, field); err != nil { return err } return nil } func (fs *findScope) findOneMergeOptions() { if fs.ctx == nil { fs.ctx = context.Background() } if fs.filter == nil { fs.filter = bson.M{} } if fs.opts == nil { fs.opts = new(options.FindOneOptions) } opts := fs.opts.(*options.FindOneOptions) if fs.skip == nil { opts.Skip = fs.skip } if fs.sort != nil { opts.Sort = fs.sort } if fs.selects != nil { opts.Projection = fs.selects } fs.opts = opts } func (fs *findScope) FindOne(doc any) error { if !goref.IsBaseStruct(doc) { return fmt.Errorf("invalid doc type, must be *struct") } fs.findOneMergeOptions() result := fs.mdbc.database.Collection(fs.scope.tableName).FindOne(fs.ctx, fs.filter, fs.opts.(*options.FindOneOptions)) if result.Err() != nil { return result.Err() } if err := result.Decode(doc); err != nil { return err } return nil } func (fs *findScope) findOneAndDeleteMergeOptions() { if fs.ctx == nil { fs.ctx = context.Background() } if fs.filter == nil { fs.filter = bson.M{} } if fs.opts == nil { fs.opts = new(options.FindOneAndDeleteOptions) } opts := fs.opts.(*options.FindOneAndDeleteOptions) if fs.sort != nil { opts.Sort = fs.sort } if fs.selects != nil { opts.Projection = fs.selects } fs.opts = opts } func (fs *findScope) FindOneAndDelete() error { fs.findOneAndDeleteMergeOptions() result := fs.mdbc.database.Collection(fs.scope.tableName).FindOneAndDelete(fs.ctx, fs.filter, fs.opts.(*options.FindOneAndDeleteOptions)) if result.Err() != nil { return result.Err() } return nil } func (fs *findScope) FindOneAndDeleteWithValue(doc any) error { if !goref.IsBaseStruct(doc) { return fmt.Errorf("invalid doc type, must be *struct") } fs.findOneAndDeleteMergeOptions() result := fs.mdbc.database.Collection(fs.scope.tableName).FindOneAndDelete(fs.ctx, fs.filter, fs.opts.(*options.FindOneAndDeleteOptions)) if result.Err() != nil { return result.Err() } if err := result.Decode(doc); err != nil { return err } return nil } func (fs *findScope) findOneAndUpdateMergeOptions() { if fs.ctx == nil { fs.ctx = context.Background() } if fs.filter == nil { fs.filter = bson.M{} } if fs.opts == nil { fs.opts = new(options.FindOneAndUpdateOptions) } opts := fs.opts.(*options.FindOneAndUpdateOptions) if fs.sort != nil { opts.Sort = fs.sort } if fs.upsert != nil { opts.Upsert = fs.upsert } if fs.selects != nil { opts.Projection = fs.selects } fs.opts = opts if goref.IsBaseStruct(fs.doc) { fs.doc = bson.M{"$set": fs.doc} } if goref.IsBaseMap(fs.doc) && !goref.ExistMapKey(fs.doc, "$set") { fs.doc = bson.M{"$set": fs.doc} } } // FindOneAndUpdate find one and update, doc type *struct or map func (fs *findScope) FindOneAndUpdate(doc any) error { fs.doc = doc fs.findOneAndUpdateMergeOptions() result := fs.mdbc.database.Collection(fs.scope.tableName).FindOneAndUpdate(fs.ctx, fs.filter, fs.doc, fs.opts.(*options.FindOneAndUpdateOptions)) if result.Err() != nil { return result.Err() } return nil } func (fs *findScope) findOneAndReplaceMergeOptions() { if fs.ctx == nil { fs.ctx = context.Background() } if fs.filter == nil { fs.filter = bson.M{} } if fs.opts == nil { fs.opts = new(options.FindOneAndReplaceOptions) } opts := fs.opts.(*options.FindOneAndReplaceOptions) if fs.sort != nil { opts.Sort = fs.sort } if fs.upsert != nil { opts.Upsert = fs.upsert } if fs.selects != nil { opts.Projection = fs.selects } fs.opts = opts if goref.IsBaseStruct(fs.doc) { fs.doc = bson.M{"$set": fs.doc} } if goref.IsBaseMap(fs.doc) && !goref.ExistMapKey(fs.doc, "$set") { fs.doc = bson.M{"$set": fs.doc} } } // FindOneAndReplace find one and replace, doc type *struct or map func (fs *findScope) FindOneAndReplace(doc any) error { fs.doc = doc fs.findOneAndReplaceMergeOptions() result := fs.mdbc.database.Collection(fs.scope.tableName).FindOneAndReplace(fs.ctx, fs.filter, fs.doc, fs.opts.(*options.FindOneAndReplaceOptions)) if result.Err() != nil { return result.Err() } return nil }