最近我在使用mongo和sort / limit时遇到了一些奇怪的行为(即他们是恕我直言,反直觉)。
我们假设我有以下集合:
> db.fred.find()
{ "_id" : ObjectId("..."), "record" : 1, "time" : ISODate("2011-12-01T00:00:00Z") }
{ "_id" : ObjectId("..."), "record" : 2, "time" : ISODate("2011-12-02T00:00:00Z") }
{ "_id" : ObjectId("..."), "record" : 3, "time" : ISODate("2011-12-03T00:00:00Z") }
{ "_id" : ObjectId("..."), "record" : 4, "time" : ISODate("2011-12-04T00:00:00Z") }
{ "_id" : ObjectId("..."), "record" : 5, "time" : ISODate("2011-12-05T00:00:00Z") }
我想要的是按时间顺序检索“记录”之前的2条记录:4加上记录4(即记录2,记录3和记录4)
天真的我是在做一些事情:
db.fred.find({time: {$lte: ISODate("2011-12-04T00:00:00Z")}}).sort({time: -1}).limit(2).sort({time: 1})
但它没有按照我预期的方式运作:
{ "_id" : ObjectId("..."), "record" : 1, "time" : ISODate("2011-12-01T00:00:00Z") }
{ "_id" : ObjectId("..."), "record" : 2, "time" : ISODate("2011-12-02T00:00:00Z") }
我认为结果将是记录2,记录3和4。
从我的回忆中,似乎2种类型在限制之前适用:
sort({time: -1}) => record 4, record 3, record 2, record 1
sort({time: -1}).limit(2) => record 4, record 3
sort({time: -1}).limit(2).sort({time: 1}) => record 1, record 2
,即第二种类型应用于find返回的游标(即整个集合),然后仅应用限制。
这里我的错误是什么?如何实现预期的行为?
BTW:在Ubuntu 11.01上运行mongo 2.0.1
答案 0 :(得分:3)
MongoDB shell懒惰地评估游标,也就是说,你完成的一系列链接操作会导致一个查询被发送到服务器,使用基于链接操作的最终状态。因此,当您说“sort({time: -1}).limit(2).sort({time: 1})
”时,第二次排序调用会覆盖第一次调用所设置的排序。
为了达到理想的效果,最好还是在应用程序代码中反转光标输出,特别是如果你限制一个小的结果集(这里你使用的是2)。这样做的确切代码取决于您使用的语言,您尚未指定。
答案 1 :(得分:3)
将sort()
多次应用于同一查询对此没有任何意义。有效排序将从最后sort()
次呼叫中获取。所以
sort({time: -1}).limit(2).sort({time: 1})
与
相同sort({time: 1}).limit(2)