Add Find with offset
This commit is contained in:
59
find.go
59
find.go
@@ -104,6 +104,65 @@ func (c *MongoClient) Find(ctx context.Context, database, name string, filter bs
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *MongoClient) FindOffset(ctx context.Context, database, name string, filter bson.M, offset, limit int64) (bson.M, error) {
|
||||||
|
// 1. Prepare to query.
|
||||||
|
collection := c.GetCollection(database, name)
|
||||||
|
|
||||||
|
finalLimit := max(limit, c.Limit)
|
||||||
|
|
||||||
|
pipeline := BuildPaginationPipeline(offset, finalLimit, filter, nil)
|
||||||
|
|
||||||
|
// 2. Query
|
||||||
|
cursor, err := collection.Aggregate(ctx, pipeline)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer cursor.Close(ctx)
|
||||||
|
|
||||||
|
// 3. Build results
|
||||||
|
var facetResults []bson.M
|
||||||
|
if err = cursor.All(ctx, &facetResults); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
root := facetResults[0]
|
||||||
|
|
||||||
|
data := root["data"].(bson.A)
|
||||||
|
|
||||||
|
metadata := root["metadata"].(bson.A)
|
||||||
|
|
||||||
|
var totalValue any
|
||||||
|
if len(metadata) != 0 {
|
||||||
|
metadataRoot := metadata[0].(bson.M)
|
||||||
|
totalValue = metadataRoot["total"]
|
||||||
|
}
|
||||||
|
|
||||||
|
var total int64
|
||||||
|
switch v := totalValue.(type) {
|
||||||
|
case int32:
|
||||||
|
total = int64(v)
|
||||||
|
case int64:
|
||||||
|
total = v
|
||||||
|
default:
|
||||||
|
total = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
hasMore := false
|
||||||
|
if int64(len(data)) > finalLimit {
|
||||||
|
hasMore = true
|
||||||
|
data = data[:finalLimit]
|
||||||
|
}
|
||||||
|
|
||||||
|
out := bson.M{
|
||||||
|
"data": data,
|
||||||
|
"offset": offset,
|
||||||
|
"limit": finalLimit,
|
||||||
|
"has_more": hasMore,
|
||||||
|
"total": total,
|
||||||
|
}
|
||||||
|
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
// func (c *MongoClient) FindNext(ctx context.Context, database, name string, filter bson.M, nextCursor string, limit int64) ([]bson.M, error) {
|
// func (c *MongoClient) FindNext(ctx context.Context, database, name string, filter bson.M, nextCursor string, limit int64) ([]bson.M, error) {
|
||||||
// collection := c.GetCollection(database, name)
|
// collection := c.GetCollection(database, name)
|
||||||
|
|
||||||
|
|||||||
12
pipeline.go
12
pipeline.go
@@ -6,13 +6,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func BuildPaginationPipeline(skip, limit int64, filter bson.M, sort bson.M) mongo.Pipeline {
|
func BuildPaginationPipeline(skip, limit int64, filter bson.M, sort bson.M) mongo.Pipeline {
|
||||||
return mongo.Pipeline{
|
pipe := mongo.Pipeline{
|
||||||
// 1. GLOBAL FILTER: Always filter first to use indexes
|
// 1. GLOBAL FILTER: Always filter first to use indexes
|
||||||
{{Key: "$match", Value: filter}},
|
{{Key: "$match", Value: filter}},
|
||||||
|
|
||||||
// 2. GLOBAL SORT: Sort here so both 'total' and 'data' facets use the same order
|
|
||||||
{{Key: "$sort", Value: sort}},
|
|
||||||
|
|
||||||
// 3. FACET: Split the pipeline into two parallel paths
|
// 3. FACET: Split the pipeline into two parallel paths
|
||||||
{{Key: "$facet", Value: bson.D{
|
{{Key: "$facet", Value: bson.D{
|
||||||
// Path A: Get the total count of documents matching the filter
|
// Path A: Get the total count of documents matching the filter
|
||||||
@@ -26,6 +23,13 @@ func BuildPaginationPipeline(skip, limit int64, filter bson.M, sort bson.M) mong
|
|||||||
}},
|
}},
|
||||||
}}},
|
}}},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2. GLOBAL SORT: Sort here so both 'total' and 'data' facets use the same order
|
||||||
|
if sort != nil {
|
||||||
|
pipe = append(pipe, bson.D{{Key: "$sort", Value: sort}})
|
||||||
|
}
|
||||||
|
|
||||||
|
return pipe
|
||||||
}
|
}
|
||||||
|
|
||||||
func BuildPaginationPipelineNext(limit int64, filter bson.M, sort bson.M) mongo.Pipeline {
|
func BuildPaginationPipelineNext(limit int64, filter bson.M, sort bson.M) mongo.Pipeline {
|
||||||
|
|||||||
Reference in New Issue
Block a user