我有类似的文档:
{_ 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数组,而不是查询数组。此外,在这个数字的情况下,我意识到有人可能会写一个否定所需范围的查询,但总的来说,我将无法写出否定。
答案 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)
幸运的是,在一阶逻辑中,涉及∀的每个语句都可以在涉及∃的等效语句中进行转换。
在您的示例中,声明:
∀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获得的 - 仅此而已。