package mongo import ( "context" "go.mongodb.org/mongo-driver/v2/bson" "git.gsuntres.com/general/commons" ) // Find is used to fetch the first page of data. func (c *MongoClient) Find(ctx context.Context, database, name string, filter bson.M, limit int64) (bson.M, error) { // 1. Prepare to query. collection := c.GetCollection(database, name) pageSize := max(limit, c.Limit) sort := bson.M{"_id": 1} if err := c.DiscriminatorCheckAndApplyToFilter(ctx, name, filter); err != nil { return nil, err } pipeline := BuildPaginationPipeline(0, pageSize + 1, filter, sort) // 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)) > pageSize { hasMore = true data = data[:pageSize] } out := bson.M{ "data": data, "has_more": hasMore, "total": total, } if hasMore { // next cursor var last bson.M = data[len(data) - 1].(bson.M) var nextCursor string lastId := last["_id"] nextCursor = EncodeCursor(lastId.(bson.ObjectID)) out["next_cursor"] = nextCursor } 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) if err := c.DiscriminatorCheckAndApplyToFilter(ctx, name, filter); err != nil { return nil, err } f := Mongofy(&Query{ Filter: filter, }) pipeline := BuildPaginationPipeline(offset, finalLimit, f, 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.D) totalValue, _ = commons.BsonDGetAny(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 }