$ orderby和$ maxScan查询修饰符与sort()和limit()shell方法的行为

时间:2013-12-17 20:01:07

标签: mongodb shell

我有一个包含以下内容的MongoDB集合:

> db.foo.find()

{ "_id" : 1, "name" : "alpha", "stamp" : ISODate("2013-06-13T12:12:51.111Z") }
{ "_id" : 2, "name" : "bravo", "stamp" : ISODate("2013-06-13T12:12:52.222Z") }
{ "_id" : 3, "name" : "charlie", "stamp" : ISODate("2013-06-13T12:12:53.333Z") }
{ "_id" : 4, "name" : "delta", "stamp" : ISODate("2013-06-13T12:12:54.444Z") }
{ "_id" : 5, "name" : "echo", "stamp" : ISODate("2013-06-13T12:12:55.555Z") }

以下是使用shell方法的结果:

> db.foo.find().sort({stamp:-1}).limit(3)

{ "_id" : 5, "name" : "echo", "stamp" : ISODate("2013-06-13T12:12:55.555Z") }
{ "_id" : 4, "name" : "delta", "stamp" : ISODate("2013-06-13T12:12:54.444Z") }
{ "_id" : 3, "name" : "charlie", "stamp" : ISODate("2013-06-13T12:12:53.333Z") }

以下是使用查询修饰符的结果:

> db.foo.find({$query:{},$orderby:{stamp:-1},$maxScan:3})

{ "_id" : 3, "name" : "charlie", "stamp" : ISODate("2013-06-13T12:12:53.333Z") }
{ "_id" : 2, "name" : "bravo", "stamp" : ISODate("2013-06-13T12:12:52.222Z") }
{ "_id" : 1, "name" : "alpha", "stamp" : ISODate("2013-06-13T12:12:51.111Z") }

看起来后者正在应用限制,然后是orderby子句,这不是我想要的。如何使用修饰符使用shell方法获得查询?

我正在尝试使用接受查询字符串的Web服务使用范围查询执行分页。所以我认为查询修饰符是可行的方法。

1 个答案:

答案 0 :(得分:2)

TL; DR

$maxScan查询修饰符不等同于游标限制。

$maxScan查询修饰符的目的是约束可能需要扫描大量文档以返回请求结果的长时间运行的查询。您可以通过添加适当的索引来提高这些查询的效率,以便MongoDB可以使用索引而不是获取文档来比较值。

对于一般查询和分页,您应该使用cursor methods,包括limit()skip()。这些是结果集游标上的方法,而不是查询修饰符。

为什么结果不同?

$maxScan查询修饰符限制处理查询时扫描的文档数。这与cursor limit不同,{{3}}会影响返回的文档数

  

db.foo.find({$查询:{},$的OrderBy:{戳:-1},$ maxScan:3})

由于您没有stamp上的索引,而是将其用作排序条件,因此结果是MongoDB将使用_id索引查找所有文档,然后对结果进行排序。 _id索引不能用于比较stamp值,因此查询匹配器必须“扫描”文档。包括$maxScan查询修饰符意味着只有扫描的前3个文档将用于结果集。

如果添加索引以匹配排序条件,您将看到预期结果:

> db.foo.ensureIndex({stamp:-1})

> db.foo.find({$query:{},$orderby:{stamp:-1},$maxScan:3})
{
    "_id" : 5,
    "name" : "echo",
    "stamp" : ISODate("2013-06-13T12:12:55.555Z")
}
{
    "_id" : 4,
    "name" : "delta",
    "stamp" : ISODate("2013-06-13T12:12:54.444Z")
}
{
    "_id" : 3,
    "name" : "charlie",
    "stamp" : ISODate("2013-06-13T12:12:53.333Z")
}