我可以进行第二次查询吗?在MongoDB游标上?

时间:2015-05-19 15:41:55

标签: mongodb indexing cursor aggregation-framework

想象一下拥有大约5,000,000个文档的集合。我需要进行basicCursor查询,根据要索引的字段太多来选择~100个文档。我们称之为basicCursorMatch。这将非常缓慢。

但是,我可以对一些索引进行bTreeCursor查询,将我的搜索限制为~500个文档。我们将此查询称为bTreeCursorMatch

我有没有办法直接对basicCursorMatch产生的光标或集合执行此操作bTreeCursorMatch

直觉我试过

var cursor = collection.find(bTreeCursorMatch);
var results = cursor.find(basicCursorMatch);

类似于collection.find(bTreeCursorMatch).find(basicCursorMatch),似乎无法正常工作。

或者,我希望我能做到这样的事情:

collection.aggregate([
    {$match: bTreeCursorMatch}, // Uses index 5,000,000 -> 500 fast
    {$match: basicCursorMatch}, // No index, 500 -> 100 'slow'
    {$sort}
]);

..但似乎我也不能这样做。有没有其他方法可以做我想做的事情?

我问的原因是因为第二个查询会有很大不同,我无法索引所有字段。但我确实希望使用bTreeCursor进行第一次查询,否则将使用basicCursor来查询整个集合。

更新

此外,通过用户输入,在使用多个basicCursor $in $eq {$gt $lt bTreeCursor reference查询的会话期间,将以不同方式查询500个文档的子选择{1}}。但在此期间,_JAVA_OPTIONS with New Variable Value: -Xmx512M子选择保持不变。我应该继续为每个用户查询执行两个查询,还是有更有效的方法来保留Error occurred during initialization of VM Incompatible minimum and maximum heap sizes specified Picked up _JAVA_OPTIONS: -Xmx512M 此集合?

1 个答案:

答案 0 :(得分:1)

实际上,您很少需要对游标运行第二次查询。您特别需要将MongoDB的工作分解为单独的可索引/不可索引的块。

如果您将查询传递给MongoDB的find方法,该方法可以通过索引中的查找部分完成,MongoDB将首先进行查找,然后对其余文档执行完整扫描。

例如,我有一个集合users,其中包含以下文档:

{ _id : 4, gender : "M", ... }

_id上有一个索引,但不是性别。 users中有大约200万个文档。

要了解MongoDB在幕后做了什么,请将explain()添加到游标(在Mongo shell中):

> db.users.find( { _id : { $gte : 1, $lt : 10 } } ).explain()
{
    "cursor" : "BtreeCursor oldId_1_state_1",
    "n" : 9,
    "nscannedObjects" : 9
}

我删除了explain返回的部分字段。基本上,光标会告诉您它是否正在使用索引,n会告诉您查询返回的文档数,nscannedObjects是查询期间扫描的对象数。在这种情况下,mongodb能够准确扫描正确数量的对象。

如果我们现在查询性别会怎么样?

> db.users.find( { _id : { $gte : 1, $lt : 10 }, gender : "F" } ).explain()
{
    "cursor" : "BtreeCursor oldId_1_state_1",
    "n" : 5,
    "nscannedObjects" : 9
}

find返回5个对象,但必须扫描9个文档。因此,它能够使用_id字段隔离正确的9个文档。然后,它浏览了所有9个文档并按性别对其进行了过滤。