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
|
||||
}
|
||||
|
||||
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) {
|
||||
// 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 {
|
||||
return mongo.Pipeline{
|
||||
pipe := mongo.Pipeline{
|
||||
// 1. GLOBAL FILTER: Always filter first to use indexes
|
||||
{{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
|
||||
{{Key: "$facet", Value: bson.D{
|
||||
// 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 {
|
||||
|
||||
Reference in New Issue
Block a user