我是MongoDB的新手,拥有一个包含字段regionId
,typeId
和timestamp
等文档的集合。
是否有一种有效的方法来检索"最新的"基于regionId
的{{1}}和typeId
对的文档?也就是说,如果文档中包含timestamp
和regionId
,则只会有一个结果,并且它不会比未选择的文档具有更小的typeId
。
我尝试使用timestamp
并使用以下聚合管道对此进行索引:
{ regionId: 1, typeId: 1, timestamp: -1 }
我无法确定它是否会返回正确的信息,因为它因此错误而失败:
{ "$match" : { "regionId" : 1234 } },
{ "$sort" : { "regionId" : 1 , "typeId" : 1 , "timestamp" : -1 } },
{ "$group" : {
"_id" : { "regionId" : "$regionId" , "typeId" : "$typeId" },
"timestamp" : { "$first" : "$timestamp" },
"otherStuff" : { "$first" : "$otherStuff" },
} }
有关如何做到这一点的任何提示吗?
答案 0 :(得分:0)
您的查询不需要进行任何聚合(即计算值或处理文档),因此您应该使用带有限制的标准find()
查询。
mongo
shell中的示例:
db.foo.find({"regionId":1234}).sort({"regionId":1,"typeId":1,"timestamp":-1 }).limit(1)
符合您的查询和排序条件的合适索引将是:
db.foo.ensureIndex({"regionId":1, "typeId":1 , "timestamp": -1})
如果你在MongoDB 2.6中添加了这个索引和explain()
查询,你会看到类似于的输出:
db.foo.find({"regionId":1234}).sort({ "regionId" : 1 ,"typeId" : 1 ,"timestamp" : -1 }).limit(1).explain()
{
"cursor": "BtreeCursor regionId_1_typeId_1_timestamp_-1",
"isMultiKey": false,
"n": 1,
"nscannedObjects": 1,
"nscanned": 1,
"scanAndOrder": false,
...
}
上面的explain output表示这是一个理想的效率查询:
cursor
值)nscanned
值)才能返回1个结果(n
值)scanAndOrder
值)排序超出内存限制104857600字节,但未选择外部排序。
您遇到的异常是因为您的聚合管道没有合适的索引可供使用,而是在进行内存中排序。 MongoDB 2.6有一个100MB memory limit用于内存排序。
如果您希望聚合管道对大型数据集使用外部排序,则有allowDiskUse
选项,但在这种情况下,异常是提示您的管道处理的数据远远多于单一结果。