Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
ff8f128fe8
|
|||
1971f1396f
|
|||
bf6c184d12
|
|||
770f5c5c64
|
|||
623c021689
|
@@ -46,6 +46,7 @@ var (
|
|||||||
TypeCursorTokenDecode = NewType("CURSOR_TOKEN_DECODE", langext.Ptr(500))
|
TypeCursorTokenDecode = NewType("CURSOR_TOKEN_DECODE", langext.Ptr(500))
|
||||||
TypeMongoFilter = NewType("MONGO_FILTER", langext.Ptr(500))
|
TypeMongoFilter = NewType("MONGO_FILTER", langext.Ptr(500))
|
||||||
TypeMongoReflection = NewType("MONGO_REFLECTION", langext.Ptr(500))
|
TypeMongoReflection = NewType("MONGO_REFLECTION", langext.Ptr(500))
|
||||||
|
TypeMongoInvalidOpt = NewType("MONGO_INVALIDOPT", langext.Ptr(500))
|
||||||
|
|
||||||
TypeWrap = NewType("Wrap", nil)
|
TypeWrap = NewType("Wrap", nil)
|
||||||
|
|
||||||
|
@@ -169,14 +169,32 @@ func (ee *ExErr) ShortLog(evt *zerolog.Event) {
|
|||||||
|
|
||||||
// RecursiveMessage returns the message to show
|
// RecursiveMessage returns the message to show
|
||||||
// = first error (top-down) that is not wrapping/foreign/empty
|
// = first error (top-down) that is not wrapping/foreign/empty
|
||||||
|
// = lowest level error (that is not empty)
|
||||||
|
// = fallback to self.message
|
||||||
func (ee *ExErr) RecursiveMessage() string {
|
func (ee *ExErr) RecursiveMessage() string {
|
||||||
|
|
||||||
|
// ==== [1] ==== first error (top-down) that is not wrapping/foreign/empty
|
||||||
|
|
||||||
for curr := ee; curr != nil; curr = curr.OriginalError {
|
for curr := ee; curr != nil; curr = curr.OriginalError {
|
||||||
if curr.Message != "" && curr.Category != CatWrap && curr.Category != CatForeign {
|
if curr.Message != "" && curr.Category != CatWrap && curr.Category != CatForeign {
|
||||||
return curr.Message
|
return curr.Message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fallback to self
|
// ==== [2] ==== lowest level error (that is not empty)
|
||||||
|
|
||||||
|
deepestMsg := ""
|
||||||
|
for curr := ee; curr != nil; curr = curr.OriginalError {
|
||||||
|
if curr.Message != "" {
|
||||||
|
deepestMsg = curr.Message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if deepestMsg != "" {
|
||||||
|
return deepestMsg
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==== [3] ==== fallback to self.message
|
||||||
|
|
||||||
return ee.Message
|
return ee.Message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
package goext
|
package goext
|
||||||
|
|
||||||
const GoextVersion = "0.0.307"
|
const GoextVersion = "0.0.312"
|
||||||
|
|
||||||
const GoextVersionTimestamp = "2023-11-09T10:00:01+0100"
|
const GoextVersionTimestamp = "2023-11-10T10:16:31+0100"
|
||||||
|
101
wmo/queryFind.go
101
wmo/queryFind.go
@@ -4,18 +4,52 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
"go.mongodb.org/mongo-driver/mongo"
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
"gogs.mikescher.com/BlackForestBytes/goext/exerr"
|
"gogs.mikescher.com/BlackForestBytes/goext/exerr"
|
||||||
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Coll[TData]) Find(ctx context.Context, filter bson.M) ([]TData, error) {
|
func (c *Coll[TData]) Find(ctx context.Context, filter bson.M, opts ...*options.FindOptions) ([]TData, error) {
|
||||||
|
|
||||||
pipeline := mongo.Pipeline{}
|
pipeline := mongo.Pipeline{}
|
||||||
pipeline = append(pipeline, bson.D{{Key: "$match", Value: filter}})
|
pipeline = append(pipeline, bson.D{{Key: "$match", Value: filter}})
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
if opt != nil && opt.Sort != nil {
|
||||||
|
pipeline = append(pipeline, bson.D{{Key: "$sort", Value: opt.Sort}})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
if opt != nil && opt.Skip != nil {
|
||||||
|
pipeline = append(pipeline, bson.D{{Key: "$skip", Value: *opt.Skip}})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
if opt != nil && opt.Limit != nil {
|
||||||
|
pipeline = append(pipeline, bson.D{{Key: "$limit", Value: *opt.Limit}})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pipeline = langext.ArrConcat(pipeline, c.extraModPipeline)
|
pipeline = langext.ArrConcat(pipeline, c.extraModPipeline)
|
||||||
|
|
||||||
cursor, err := c.coll.Aggregate(ctx, pipeline)
|
for _, opt := range opts {
|
||||||
|
if opt != nil && opt.Projection != nil {
|
||||||
|
pipeline = append(pipeline, bson.D{{Key: "$project", Value: opt.Projection}})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
convOpts := make([]*options.AggregateOptions, 0, len(opts))
|
||||||
|
for _, v := range opts {
|
||||||
|
vConv, err := convertFindOpt(v)
|
||||||
|
if err != nil {
|
||||||
|
return nil, exerr.Wrap(err, "mongo-aggregation failed").Any("pipeline", pipeline).Str("collection", c.Name()).Build()
|
||||||
|
}
|
||||||
|
convOpts = append(convOpts, vConv)
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor, err := c.coll.Aggregate(ctx, pipeline, convOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, exerr.Wrap(err, "mongo-aggregation failed").Any("pipeline", pipeline).Str("collection", c.Name()).Build()
|
return nil, exerr.Wrap(err, "mongo-aggregation failed").Any("pipeline", pipeline).Str("collection", c.Name()).Build()
|
||||||
}
|
}
|
||||||
@@ -27,3 +61,66 @@ func (c *Coll[TData]) Find(ctx context.Context, filter bson.M) ([]TData, error)
|
|||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// converts FindOptions to AggregateOptions
|
||||||
|
func convertFindOpt(v *options.FindOptions) (*options.AggregateOptions, error) {
|
||||||
|
if v == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
r := options.Aggregate()
|
||||||
|
|
||||||
|
if v.AllowDiskUse != nil {
|
||||||
|
r.SetAllowDiskUse(*v.AllowDiskUse)
|
||||||
|
}
|
||||||
|
if v.AllowPartialResults != nil {
|
||||||
|
return nil, exerr.New(exerr.TypeMongoInvalidOpt, "Invalid option 'AllowPartialResults' (cannot convert to AggregateOptions)").Build()
|
||||||
|
}
|
||||||
|
if v.BatchSize != nil {
|
||||||
|
r.SetBatchSize(*v.BatchSize)
|
||||||
|
}
|
||||||
|
if v.Collation != nil {
|
||||||
|
r.SetCollation(v.Collation)
|
||||||
|
}
|
||||||
|
if v.Comment != nil {
|
||||||
|
r.SetComment(*v.Comment)
|
||||||
|
}
|
||||||
|
if v.CursorType != nil {
|
||||||
|
return nil, exerr.New(exerr.TypeMongoInvalidOpt, "Invalid option 'CursorType' (cannot convert to AggregateOptions)").Build()
|
||||||
|
}
|
||||||
|
if v.Hint != nil {
|
||||||
|
r.SetHint(v.Hint)
|
||||||
|
}
|
||||||
|
if v.Max != nil {
|
||||||
|
return nil, exerr.New(exerr.TypeMongoInvalidOpt, "Invalid option 'Max' (cannot convert to AggregateOptions)").Build()
|
||||||
|
}
|
||||||
|
if v.MaxAwaitTime != nil {
|
||||||
|
r.SetMaxAwaitTime(*v.MaxAwaitTime)
|
||||||
|
}
|
||||||
|
if v.MaxTime != nil {
|
||||||
|
r.SetMaxTime(*v.MaxTime)
|
||||||
|
}
|
||||||
|
if v.Min != nil {
|
||||||
|
return nil, exerr.New(exerr.TypeMongoInvalidOpt, "Invalid option 'Min' (cannot convert to AggregateOptions)").Build()
|
||||||
|
}
|
||||||
|
if v.NoCursorTimeout != nil {
|
||||||
|
return nil, exerr.New(exerr.TypeMongoInvalidOpt, "Invalid option 'NoCursorTimeout' (cannot convert to AggregateOptions)").Build()
|
||||||
|
}
|
||||||
|
if v.OplogReplay != nil {
|
||||||
|
return nil, exerr.New(exerr.TypeMongoInvalidOpt, "Invalid option 'OplogReplay' (cannot convert to AggregateOptions)").Build()
|
||||||
|
}
|
||||||
|
if v.ReturnKey != nil {
|
||||||
|
return nil, exerr.New(exerr.TypeMongoInvalidOpt, "Invalid option 'ReturnKey' (cannot convert to AggregateOptions)").Build()
|
||||||
|
}
|
||||||
|
if v.ShowRecordID != nil {
|
||||||
|
return nil, exerr.New(exerr.TypeMongoInvalidOpt, "Invalid option 'ShowRecordID' (cannot convert to AggregateOptions)").Build()
|
||||||
|
}
|
||||||
|
if v.Snapshot != nil {
|
||||||
|
return nil, exerr.New(exerr.TypeMongoInvalidOpt, "Invalid option 'Snapshot' (cannot convert to AggregateOptions)").Build()
|
||||||
|
}
|
||||||
|
if v.Let != nil {
|
||||||
|
r.SetLet(v.Let)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
@@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
"go.mongodb.org/mongo-driver/mongo"
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
ct "gogs.mikescher.com/BlackForestBytes/goext/cursortoken"
|
|
||||||
"gogs.mikescher.com/BlackForestBytes/goext/exerr"
|
"gogs.mikescher.com/BlackForestBytes/goext/exerr"
|
||||||
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
||||||
pag "gogs.mikescher.com/BlackForestBytes/goext/pagination"
|
pag "gogs.mikescher.com/BlackForestBytes/goext/pagination"
|
||||||
@@ -21,18 +20,15 @@ func (c *Coll[TData]) Paginate(ctx context.Context, filter pag.Filter, page int,
|
|||||||
|
|
||||||
pipelineSort := mongo.Pipeline{}
|
pipelineSort := mongo.Pipeline{}
|
||||||
pipelineFilter := mongo.Pipeline{}
|
pipelineFilter := mongo.Pipeline{}
|
||||||
pf1 := "_id"
|
sort := bson.D{}
|
||||||
pd1 := ct.SortASC
|
|
||||||
|
|
||||||
if filter != nil {
|
if filter != nil {
|
||||||
pipelineFilter = filter.FilterQuery()
|
pipelineFilter = filter.FilterQuery()
|
||||||
pf1, pd1 = filter.Pagination()
|
sort = filter.Sort()
|
||||||
}
|
}
|
||||||
|
|
||||||
if pd1 == ct.SortASC {
|
if len(sort) != 0 {
|
||||||
pipelineSort = append(pipelineSort, bson.D{{Key: "$sort", Value: bson.D{{Key: pf1, Value: +1}}}})
|
pipelineSort = append(pipelineSort, bson.D{{Key: "$sort", Value: sort}})
|
||||||
} else if pd1 == ct.SortDESC {
|
|
||||||
pipelineSort = append(pipelineSort, bson.D{{Key: "$sort", Value: bson.D{{Key: pf1, Value: -1}}}})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pipelinePaginate := mongo.Pipeline{}
|
pipelinePaginate := mongo.Pipeline{}
|
||||||
@@ -44,7 +40,7 @@ func (c *Coll[TData]) Paginate(ctx context.Context, filter pag.Filter, page int,
|
|||||||
}
|
}
|
||||||
|
|
||||||
pipelineCount := mongo.Pipeline{}
|
pipelineCount := mongo.Pipeline{}
|
||||||
pipelinePaginate = append(pipelinePaginate, bson.D{{Key: "$count", Value: "count"}})
|
pipelineCount = append(pipelineCount, bson.D{{Key: "$count", Value: "count"}})
|
||||||
|
|
||||||
pipelineList := langext.ArrConcat(mongo.Pipeline{}, pipelineFilter, pipelinePaginate, c.extraModPipeline)
|
pipelineList := langext.ArrConcat(mongo.Pipeline{}, pipelineFilter, pipelinePaginate, c.extraModPipeline)
|
||||||
pipelineTotalCount := langext.ArrConcat(mongo.Pipeline{}, pipelineFilter, pipelineCount)
|
pipelineTotalCount := langext.ArrConcat(mongo.Pipeline{}, pipelineFilter, pipelineCount)
|
||||||
|
Reference in New Issue
Block a user