PHP - mongodb 客户端 - 跳过和限制使用

Posted

技术标签:

【中文标题】PHP - mongodb 客户端 - 跳过和限制使用【英文标题】:PHP - mongodb client - skip and limit usage 【发布时间】:2013-04-04 15:47:16 【问题描述】:

可能这是一个愚蠢的问题,但无论如何我有疑问。

请看一下这个查询:

db.posts.find( "blog": "myblog", 
                "post_author_id": 649, 
                "shares.total":  "$gt": 0  )
        .limit(10)
        .skip(1750)
        .sort( "shares.total": -1, "tstamp_published": -1 );

实际上我在 mongodb profiler 中看到了这个报告:

mongos> db.system.profile.find( nreturned :  $gt : 1000  ).limit(10).sort(  millis : 1  ).pretty();

    "ts" : ISODate("2013-04-04T13:28:08.906Z"),
    "op" : "query",
    "ns" : "mydb.posts",
    "query" : 
        "$query" : 
            "blog" : "myblog",
            "post_author_id" : 649,
            "shares.total" : 
                "$gt" : 0
            
        ,
        "$orderby" : 
            "shares.total" : -1,
            "tstamp_published" : -1
        
    ,
    "ntoreturn" : 1760,
    "nscanned" : 12242,
    "scanAndOrder" : true,
    "nreturned" : 1760,
    "responseLength" : 7030522,
    "millis" : 126,
    "client" : "10.0.232.69",
    "user" : ""

现在的问题是:当我明确要求跳过 1750 时,为什么 mongodb 会返回 1760 文档?

这是我当前的 Mongodb 版本,在集群/分片中。

mongos> db.runCommand("buildInfo")

    "version" : "2.0.2",
    "gitVersion" : "514b122d308928517f5841888ceaa4246a7f18e3",
    "sysInfo" : "Linux bs-linux64.10gen.cc 2.6.21.7-2.ec2.v1.2.fc8xen #1 SMP Fri Nov 20 17:48:28 EST 2009 x86_64 BOOST_LIB_VERSION=1_41",
    "versionArray" : [
        2,
        0,
        2,
        0
    ],
    "bits" : 64,
    "debug" : false,
    "maxBsonObjectSize" : 16777216,
    "ok" : 1

【问题讨论】:

【参考方案1】:

现在的问题是:当我明确要求跳过 1750 时,为什么 mongodb 会返回 1760 文档?

因为服务器端 skip() 正是这样做的:它迭代前 1750 个结果,然后再获得 10 个结果(根据限制)。

正如@devesh 所说,这就是为什么应该避免非常大的分页,因为 MongoDB 没有有效地使用 skip()limit() 的索引。

【讨论】:

【参考方案2】:

我认为你已经中了靶心,我认为这就是为什么 mongoDB 文档要求我们避免大跳过 http://docs.mongodb.org/manual/reference/method/cursor.skip/ 的原因。请看这里它会回答你的结果。使用将与 $gt 运算符一起使用的其他键会快得多。就像第 1 页中最后一个键的日期时间戳一样,然后在日期时间上使用 $get。

cursor.skip() 方法通常代价高昂,因为它需要服务器从集合或索引的开头步行以获取偏移或跳过位置,然后再开始返回结果

【讨论】:

我不能使用 Datetime,因为它是一个博客。当发布新帖子时,所有现有帖子,其日期时间只是“转移”。即使我直接转到 page/200 我也不知道第一次发布此页面的日期时间。

以上是关于PHP - mongodb 客户端 - 跳过和限制使用的主要内容,如果未能解决你的问题,请参考以下文章

实体框架/Linq to SQL:跳过和采取

在 MongoDB 中建模访问控制

文件拷贝跳过和忽略

如何在 Spring 批处理中重复一个步骤

Python单元测试--使用装饰器实现测试跳过和预期故障

在 LINQ to Entities 中有 10 个不同的对象之前,如何跳过和获取对象?