mongodb查询将doc数组中的每个元素与条件匹配

时间:2011-05-18 01:04:38

标签: arrays mongodb

我有类似的文档:

{_ id:1,值:[2,3,4]}

{_ id:2,值:[4]}

{_ id:3,值:[3,4,5,6,7,8,9,10,11]}

其中每个doc都有一个数组。我需要一个只返回文档的查询,如果它的数组的EACH元素符合所需的条件(而不是任何元素匹配)。

EG。类似(但不是)的东西

{'values':{'$ gt':1,'$ lt':5}})

哪个会成功返回前两个但不是第三个doc,而不是全部 第三个doc的数组'values'的元素符合条件。

显然mongodb在数组查询中使用隐​​式OR,而我需要AND。

我想我可以手动索引每个元素,例如:

collection.find({values.0:{$ gt:1,$ lt:5},values.1:{$ gt:1,$ lt:5},... values.n:{$ gt :1,$ lt:5}})但这对我的高动态数组来说很痛苦。

有更好的方法吗?

注意:我在mongodb-user上询问了这个问题,但是mongodb的新手与$ all运算符混淆了。这里我关注doc数组,而不是查询数组。此外,在这个数字的情况下,我意识到有人可能会写一个否定所需范围的查询,但总的来说,我将无法写出否定。

5 个答案:

答案 0 :(得分:7)

除了手动迭代文档并检查数组中的每个值之外,我认为还没有办法做到这一点。这将非常缓慢,因为它必须在每个文档上执行JavaScript,并且无法利用col.values之上的任何索引。

即使$where JavaScript表达式查询在这里似乎也不起作用,因为可能是因为查询包含回调并且过于复杂:

db.col.find("this.values.every(function(v) { return (v > 1 && v < 5) })")

<击>

编辑:对于某些查询,包括此查询,JavaScript $where表达式需要一个return语句,所以这样可以正常工作:

db.col.find("return this.values.every(function(v) { return (v > 1 && v < 5) })")

答案 1 :(得分:5)

与大多数(如果不是全部)数据库一样,MongoDB只实现existential quantificator(∃,exists)及其否定(∄,不存在。)它没有universal quantificator(Mong) ,对所有人来说)也不是否定,因为他们无法使用指数进行优化,因此在实践中没有用处。

幸运的是,在一阶逻辑中,涉及∀的每个语句都可以在涉及∃的等效语句中进行转换。

在您的示例中,声明:

  

∀x∈值:x> 1∧x<1 5

或“所有值均为&gt; 1且&lt; 5”等同于

  

∄x∈值:¬(x>1∧x<5)

或“没有值&gt; 1和&lt; 5”由De Morgan's laws变为:

  

∄x∈值:x≤1∨x≥5

或“没有≤1或≥5的值”

后者可以通过多种方式在MongoDB中表达,例如:

> db.test.remove()
> db.test.insert({_id: 1, values: [2, 3, 4]})
> db.test.insert({_id: 2, values: [4]})
> db.test.insert({_id: 3, values: [3, 4, 5, 6, 7, 8, 9, 10, 11]})

> db.test.find({$nor: [{values: {$lte: 1}}, {values: {$gte: 5}}]})
{ "_id" : 1, "values" : [  2,  3,  4 ] }
{ "_id" : 2, "values" : [  4 ] }

答案 2 :(得分:1)

目前MongoDB AFAIK无法做到这一点。

编辑:我的立场得到了纠正。有可能它只是不可索引,所以它对我来说是“不可能的”领域。见下文。你也可以映射reduce。这些就像MongoDB中的“走出监狱”牌一样,但与那些卡一样,与真正的运营商相比,存在严重的缺点。

答案 3 :(得分:1)

你会牺牲速度,但你可以使用JavaScript expression,直接传递给find()$where

你可以循环遍历数组中的元素,只有在所有元素满足你的条件时才返回true。

答案 4 :(得分:0)

线程

http://groups.google.com/group/mongodb-user/browse_thread/thread/dad19e28c1acbd49

解释了您的选择。

正如'chx'写道:这是不可能的。您现在知道$ all和$或运算符的功能。这就是你所拥有的并从MongoDB获得的 - 仅此而已。