想象一下拥有大约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
此集合?
答案 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个文档并按性别对其进行了过滤。