mdbc/find.go

319 lines
7.1 KiB
Go

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
}