首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用mongodb/mongo-go-driver进行高效分页

如何使用mongodb/mongo-go-driver进行高效分页
EN

Stack Overflow用户
提问于 2018-10-06 17:49:49
回答 3查看 5.7K关注 0票数 1

我在下面的文章中读到,使用_id的自然排序来执行分页更有效,因为跳过总是从集合的开头开始。

Fast and Efficient Pagination in MongoDB

代码语言:javascript
复制
// Page 1
db.students.find().limit(10)

// Page 2
last_id = ...  # logic to get last_id
db.students.find({'_id': {'$gt': last_id}}).limit(10)

但我不知道如何使用mongodb/mongo-go-driver执行上述操作。

EN

回答 3

Stack Overflow用户

发布于 2018-10-08 20:21:47

cursor.skip()方法要求服务器在开始返回结果之前从输入结果集的开头进行扫描。随着偏移量的增加,cursor.skip()将变得更慢。虽然范围查询可以使用索引来避免扫描不需要的文档,但与使用cursor.skip()进行分页相比,随着偏移量的增加,通常会产生更好的性能。有关MongoDB: Pagination Example的详细信息,请参阅

使用当前版本的mongo-go-driver (v0.0.15).An示例进行分页,首先显示最新条目:

代码语言:javascript
复制
func Paginate(collection *mongo.Collection, startValue objectid.ObjectID, nPerPage int64) ([]bson.Document, *bson.Value, error) {

    // Query range filter using the default indexed _id field. 
    filter := bson.VC.DocumentFromElements(
        bson.EC.SubDocumentFromElements(
            "_id",
            bson.EC.ObjectID("$gt", startValue),
        ),
    )

    var opts []findopt.Find
    opts = append(opts, findopt.Sort(bson.NewDocument(bson.EC.Int32("_id", -1))))
    opts = append(opts, findopt.Limit(nPerPage))

    cursor, _ := collection.Find(context.Background(), filter, opts...)

    var lastValue *bson.Value
    var results []bson.Document
    for cursor.Next(context.Background()) {
        elem := bson.NewDocument()
        err := cursor.Decode(elem)
        if err != nil {
            return results, lastValue, err
        }
        results = append(results, *elem)
        lastValue = elem.Lookup("_id")
    }

    return results, lastValue, nil
}

调用上面的分页函数的示例:

代码语言:javascript
复制
database := client.Database("databaseName")
collection := database.Collection("collectionName")
startObjectID, _ := objectid.FromHex("5bbafea2b5e14ee3a298fa4a")

// Paginate only the latest 20 documents 
elements, lastID, err := Paginate(collection, startObjectID, 20)
for _, e := range elements {
    fmt.Println(&e)
}
// Last seen ObjectID can be used to call next Paginate() 
fmt.Println("Last seen ObjectID: ", lastID.ObjectID())

请注意,您还可以用另一个索引字段替换_id字段。

票数 1
EN

Stack Overflow用户

发布于 2020-10-30 11:22:20

你可以创建一个新的函数,别忘了传递http.writer来读取参数。

代码语言:javascript
复制
func Pagination(r *http.Request, FindOptions *options.FindOptions) (int64, int64) {
    if r.URL.Query().Get("page") != "" && r.URL.Query().Get("limit") != "" {
        page, _ := strconv.ParseInt(r.URL.Query().Get("page"), 10, 32)
        limit, _ := strconv.ParseInt(r.URL.Query().Get("limit"), 10, 32)
        if page == 1 {
            FindOptions.SetSkip(0)
            FindOptions.SetLimit(limit)
            return page, limit
        }

        FindOptions.SetSkip((page - 1) * limit)
        FindOptions.SetLimit(limit)
        return page, limit

    }
    FindOptions.SetSkip(0)
    FindOptions.SetLimit(0)
    return 0, 0
}

只要打个电话

代码语言:javascript
复制
Pagination(r, options)

示例

代码语言:javascript
复制
options := options.Find()
page, limit := parameter.Pagination(r, options)
// page, limit as response for header payload
票数 1
EN

Stack Overflow用户

发布于 2022-02-24 13:51:44

如果不需要分页,则设置page=0和limit=0。

代码语言:javascript
复制
func GetUsers (page, limit int) {
    filter := bson.D{{}} // selects all documents
    options := new(options.FindOptions)
    if limit != 0 {
        if page == 0 {
            page = 1
        }
        options.SetSkip(int64((page - 1) * limit))
        options.SetLimit(int64(limit))
    }

    cursor, err := mongoCollection.Find(context.TODO(), filter, options)
...
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52677785

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档