MongoDB findOne 和 $or 的参数顺序或层次是否重要?【性能】
我想问的是,比如说有两个条件:如果第一个条件成立,是否会跳过检查第二个条件?
doc = collection.find_one(
{'$or': [
{
'k': kind,
'i': int(pk)
},
{
'children.k': kind,
'children.i': int(pk)
}
]
}, { '_id': False})
我希望在找到第一个条件匹配的时候就停止进一步的搜索,这样就不会再去找更低层次的子项了。
这和$OR
中参数的顺序有关吗,还是说mongodb自己聪明地知道层级关系,从而影响findOne
的搜索顺序?
2 个回答
我希望在找到第一个条件匹配后就停止进一步搜索,这样就不会再去查找子级的内容了。
你需要问自己一个问题:MongoDB是怎么知道在$or
的两边,哪一边满足条件?它怎么知道那些不满足第一个条件的文档也不满足第二个条件呢?
假设我有一组文档,一半是{a:1,b:1}
,另一半是{b:2}
,那么如果你根本不知道第二半是什么样的,怎么能知道a:1 OR b:1
是由第一半满足的呢?
简单的回答是,它并不知道。MongoDB必须同时检查两个条件(通过并行查询,然后合并重复的结果),所以顺序并不重要,除非是$and
的情况。在这种情况下,顺序的重要性体现在索引上,而不是查询本身,因为查询会被调整,以优化获取结果的最快路径。
实际上,MongoDB的工作方式是针对每个条件发出一个“查询”。这实际上解释了它的行为:http://docs.mongodb.org/manual/reference/operator/query/or/#behaviors
在使用带有$or查询的索引时,$or的每个条件都可以使用自己的索引。
是的,顺序很重要,这也是使用数组作为参数的一大原因,因为数组是有顺序的。
这其实被称为“短路”评估。也就是说,只有当第一个条件不满足时,才会去检查下一个条件,依此类推。
我们可以用一个这样的集合来说明:
{ "a": 1 },
{ "a": 2, "b": 1 }
然后是下面这个查询:
db.collection.find({ "$or": [ { "a": 1 }, { "b": 1 } ] })
这个查询会找到两个文档,因为虽然第一个文档没有“b”这个元素,但第一个条件还是满足了。在第二个文档中,由于第一个条件不满足,所以就用了第二个条件来进行匹配。