diff --git a/mongox/common/loadarray.go b/mongox/common/loadarray.go new file mode 100644 index 0000000..0e1440c --- /dev/null +++ b/mongox/common/loadarray.go @@ -0,0 +1,73 @@ +package common + +import ( + "reflect" + + "github.com/mainnika/mongox-go-driver/mongox" + "github.com/mainnika/mongox-go-driver/mongox/errors" + "github.com/mainnika/mongox-go-driver/mongox/query" + "github.com/mongodb/mongo-go-driver/mongo/options" +) + +// LoadArray loads an array of documents from the database by query +func LoadArray(db *mongox.Database, target interface{}, composed *query.Query) error { + + targetV := reflect.ValueOf(target) + targetT := targetV.Type() + + targetK := targetV.Kind() + if targetK != reflect.Ptr { + panic(errors.InternalErrorf("target is not a ptr")) + } + + targetSliceV := targetV.Elem() + targetSliceT := targetT.Elem() + if targetSliceT.Kind() != reflect.Slice { + panic(errors.InternalErrorf("target should be a ptr to a slice")) + } + + targetSliceElemT := targetSliceT.Elem() + if targetSliceElemT.Kind() != reflect.Ptr { + panic(errors.InternalErrorf("target slice should contain ptrs")) + } + + dummy := reflect.Zero(targetSliceElemT) + collection := db.GetCollectionOf(dummy.Interface()) + opts := &options.FindOptions{} + + if composed.Sorter() != nil { + opts.Sort = composed.Sorter().Sort() + } + if composed.Limiter() != nil { + limit := int64(composed.Limiter().Limit()) + opts.Limit = &limit + } + + result, err := collection.Find(db.Context(), composed.M(), opts) + if err != nil { + return errors.InternalErrorf("can't create find result: %s", err) + } + + defer result.Close(db.Context()) + var i int + + for i = 0; result.Next(db.Context()); i++ { + if targetSliceV.Len() == i { + elem := reflect.New(targetSliceElemT.Elem()) + if result.Decode(elem.Interface()) != nil { + continue + } + + targetSliceV = reflect.Append(targetSliceV, elem) + // currentv = currentv.Slice(0, currentv.Cap()) + continue + } + + result.Decode(targetSliceV.Index(i).Interface()) + } + + targetSliceV = targetSliceV.Slice(0, i) + targetV.Elem().Set(targetSliceV) + + return nil +}