2012-03-16 72 views
3

如何将MongoDB的评价此查询:

db.testCol.find(
{ 
    "$or" : [ {a:1, b:12}, {b:9, c:15}, {c:10, d:"foo"} ] 
}); 

当文档扫描值,如果第一OR说法是正确的,对其他报表中也进行评估?

从逻辑上讲,如果MongoDB被优化,OR语句中的其他值不应该被评估,但我不知道MongoDB是如何实现的。

更新: 我更新了我的查询,因为它是错误的,它没有正确解释我想要完成的工作。我需要找到一组具有不同属性的文档,如果找到这些属性的组合,则必须返回该文档。

的SQL相当于我查询的是:

SELECT * FROM testCol 
WHERE (a = 1 AND b = 12) OR (b = 9 AND c = 15) OR (c = 10 AND d = 'foo'); 

回答

3

的MongoDB将执行$或操作的每个条款作为一个单独的查询和删除重复项作为后处理途径。因此,每个子句都可以使用通常非常有用的单独索引。

换句话说,它不会查看1个文档,查看哪些OR子句适用,并在第一个子句匹配时进行提前清除。相反,它会为每个子句执行完整的数据集查询,并在事实之后进行重复数据删除。这看起来似乎效率不高,但实际上它几乎总是更快,因为第一种方法最多只能对所有子句中的一个索引进行打击,而这对于很少有效的子句是很有效的。

+0

基本上,如果我使用$或在非索引字段上搜索,查询会很慢,因为它会为每个语句执行全表扫描(如果我理解正确)? – 2012-03-16 16:42:25

+0

是的,但无论如何,执行全表扫描的查询都会很慢。在$的情况下,随着添加更多子句,它将逐渐变慢。实际上,没有人会对“大数据”数据库进行无索引查询。 – 2012-03-16 17:00:52

+0

当我通过更改$或语句中的项目顺序进行解释时,我在nscanned中看到了两个不同的结果。这个查询是愚蠢的,因为它通过定义将包括查询中第一个的结果,但它表明mongo在某些情况下不会分别处理这两个项目:https://gist.github.com/0c9b9b74655ddab7f820 – Spencer 2012-03-16 19:20:42

1

编辑:蒙戈只在重复数据删除过程中跳过的文件,而不是在表扫描。

Mongo不会检查已经是结果集一部分的文档。所以如果你的第一个{a:1,b:12}返回文档的100%,Mongo就完成了。

因为这个原因,你想要把最多的文档作为你的第一个评估语句。如果您的第一个项目只抓取1%的文档,则后续项目需要扫描其他99%。

这就是说,您正在使用$或在单个键中查找值。我想你想用这个$ in。

在这里看到更多:

http://books.google.com/books?id=BQS33CxGid4C&lpg=PA48&ots=PqvQJPRUoe&dq=mongo%20tips%20and%20tricks%20%22OR-query%22&pg=PA48#v=onepage&q&f=false

+0

对不起......我的查询是错误的,我试图完成不同的事情。我纠正了它,并添加了额外的解释。 – 2012-03-16 14:07:17

+0

我不认为这是正确的。单独的$或子句被视为单独的查询,并且当结果结合时弹出重复项,而不是在执行第二个子句之前主动过滤掉第一个子句的结果(比如通过底层$ nin)。 – 2012-03-16 16:16:14

+0

来自Kristina Chodorow的书“MongoDB开发人员的50个技巧和诀窍” “OR风格的查询与AND查询完全相反:尝试首先放置最具包容性的子句,因为MongoDB必须不断检查不是部分的文档每场比赛的结果集。“ 我解释错了吗?然后,她可能会提到重复过程,这样做当然不会带来太多好处。 – Spencer 2012-03-16 18:23:34