【发布时间】:2014-03-27 03:44:06
【问题描述】:
我有一个(希望很快)关于复合索引上的 MongoDB 查询的问题。
假设我有一个数据集(例如 cmets),我想按分数降序排序,然后按日期:
{ "score" : 10, "date" : ISODate("2014-02-24T00:00:00.000Z"), ...}
{ "score" : 10, "date" : ISODate("2014-02-18T00:00:00.000Z"), ...}
{ "score" : 10, "date" : ISODate("2014-02-12T00:00:00.000Z"), ...}
{ "score" : 9, "date" : ISODate("2014-02-22T00:00:00.000Z"), ...}
{ "score" : 9, "date" : ISODate("2014-02-16T00:00:00.000Z"), ...}
...
到目前为止,我的理解是我可以创建一个复合索引来支持这个查询,它看起来像{"score":-1,"date":-1}。 (为了清楚起见,我没有在索引中使用日期,而是使用 ObjectID 来表示唯一的、大致基于时间的顺序)
现在,假设我想支持通过 cmets 进行分页。第一页很简单,我可以在光标末尾粘贴一个.limit(n) 选项。我正在苦苦挣扎的是继续搜索。
我一直在参考 Kristina Chodorow 的 MongoDB:权威指南。在这本书中,Kristina 提到在大型数据集上使用 skip() 性能不是很好,并建议对上次看到的结果(例如上次看到的日期)的参数使用范围查询。
我想做的是执行一个作用于两个字段的范围查询,但将第二个字段视为第一个字段的次要字段(就像索引已排序一样。)因为我的复合索引已经按顺序排序我想要,似乎应该有某种方法可以通过指向索引中的特定元素并按排序顺序遍历它来跳入搜索。但是,根据我对 MongoDB 中查询的(不可否认的初步)理解,这似乎是不可能的。
据我所知,我有三个选择:
- 还是使用
skip() - 使用 $or 查询或两个不同的查询:
{$or : [{"score" : lastScore, "date" : { $lt : lastDate}}, {'score' : {$lt : lastScore}]} - 使用
$max特殊查询选项
数字 3 对我来说似乎最接近理想,但参考文本指出“您通常应该使用“$lt”而不是“$max”。
总结一下,我有几个问题:
- 是否有一些方法可以执行我所描述的操作,但我可能错过了? (跳入索引并按排序顺序遍历)
- 如果不是,在我描述的三个选项(或任何我忽略的选项)中,哪个(非常笼统地说)在复合指数下的表现最一致?
- 为什么在大多数情况下首选 $lt 而不是 $max?
提前感谢您的帮助!
【问题讨论】:
标签: mongodb mongodb-query