MongoDB findOne 和 $or 的参数顺序或层次是否重要?【性能】

5 投票
2 回答
1463 浏览
提问于 2025-04-18 18:49

我想问的是,比如说有两个条件:如果第一个条件成立,是否会跳过检查第二个条件?

doc = collection.find_one(
    {'$or': [
              {
               'k': kind,
               'i': int(pk)
              },
              {
               'children.k': kind, 
               'children.i': int(pk)
              }

            ]
    }, { '_id': False})

我希望在找到第一个条件匹配的时候就停止进一步的搜索,这样就不会再去找更低层次的子项了。

这和$OR中参数的顺序有关吗,还是说mongodb自己聪明地知道层级关系,从而影响findOne的搜索顺序?

2 个回答

4

我希望在找到第一个条件匹配后就停止进一步搜索,这样就不会再去查找子级的内容了。

你需要问自己一个问题: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的每个条件都可以使用自己的索引。

4

是的,顺序很重要,这也是使用数组作为参数的一大原因,因为数组是有顺序的。

这其实被称为“短路”评估。也就是说,只有当第一个条件不满足时,才会去检查下一个条件,依此类推。

我们可以用一个这样的集合来说明:

{ "a": 1 },
{ "a": 2, "b": 1 }

然后是下面这个查询:

db.collection.find({ "$or": [ { "a": 1 }, { "b": 1 } ] })

这个查询会找到两个文档,因为虽然第一个文档没有“b”这个元素,但第一个条件还是满足了。在第二个文档中,由于第一个条件不满足,所以就用了第二个条件来进行匹配。

撰写回答