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

ric*_*pan 5 arrays mongodb

我有类似的文档:

{_id:1,值:[2,3,4]}

{_id:2,值:[4]}

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

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

例如.像(但不是)的东西

{'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数组,而不是查询数组.此外,在这个数字的情况下,我意识到可能会编写一个否定所需范围的查询,但一般来说,我将无法编写否定.

Chr*_*tow 7

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

甚至一个$表示 JavaScript表达式查询在这里似乎没有用,因为可能是因为查询包含一个回调并且过于复杂:

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

编辑:对于某些查询,包括这一个,JavaScript $ where表达式需要一个return语句,所以这很好:

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


Tob*_*bia 5

与大多数(如果不是全部)数据库一样,MongoDB只实现存在量化器(∃,存在)及其否定(∄,不存在).它没有通用量化器(∀,对所有人)也没有否定,因为它们无法使用索引进行优化,因此在实践中没有用处.

幸运的是,在一阶逻辑中,涉及∀的每个语句都可以转换为涉及∃的等价语句.

在您的示例中,声明:

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

或"所有值> 1且<5"相当于

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

或者" 没有 > 1和<5"的价值,根据德摩根的法律变为:

∄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 ] }
Run Code Online (Sandbox Code Playgroud)