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

发布于 2024-11-08 02:25:17 字数 683 浏览 0 评论 0原文

我有与此类似的文档:

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

{_id: 2,values:[4]}

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

其中每个文档都有一个数组。我需要一个查询,仅当其数组的每个元素匹配所需的条件(而不是任何元素匹配)时才返回文档。

例如。类似 (但不是)

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

的东西会成功返回前两个文档,但不会返回第三个文档,因为并非所有文档 第三个文档的数组“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 运算符产生了混淆。这里我关心的是文档数组,而不是查询数组。另外,在这种数字情况下,我意识到人们可能会编写一个查询来否定所需的范围,但一般来说我无法编写否定。

I have docs analogous to this:

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

{_id: 2, values: [4] }

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

in which each doc has an array. I need a query that only returns the doc if EACH element of its array match the desired criteria (rather than if ANY element matches).

Eg. something like (but not)

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

which would successfully return the first two but not the third doc, as not all
elements of the third doc's array 'values' match the criteria.

Apparently mongodb uses an implicit OR in queries on arrays, whereas I need AND.

I guess I could manually index each element, eg.:

collection.find({values.0: {$gt:1,$lt:5}, values.1:{$gt:1,$lt:5}, ... values.n:{$gt:1,$lt:5}}) but this is a pain with my highly dynamic arrays.

Is there a better way?

Note: I asked this over at mongodb-user but being new to mongodb generated confusion with $all operator. Here I am concerned about the doc array, not a query array. Also, in this numeric case I realize one might write a query that negates the range desired, but in general I won't be able to write the negation.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

枯叶蝶 2024-11-15 02:25:17

我认为除了手动迭代文档并检查数组中的每个值之外,还没有任何方法可以做到这一点。这会非常慢,因为它必须在每个文档上执行 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) })")

I don't think there's any way to do this yet, apart from manually iterating through your documents and checking each value in the array. That's going to be quite slow because it has to execute JavaScript on each document, and can't take advantage of any index over col.values.

Even a $where JavaScript expression query doesn't seem work here because, possibly because the query contains a callback and is too complex:

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

Edit: For some queries, including this one, the JavaScript $where expression needs a return statement, so this works fine:

db.col.find("return this.values.every(function(v) { return (v > 1 && v < 5) })")
梦醒灬来后我 2024-11-15 02:25:17

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 ] }

MongoDB, like most (if not all) databases, only implements the existential quantificator (∃, exists) and its negation (∄, does not exist.) It does not have the universal quantificator (∀, for all) nor its negation, because they cannot be optimized using indices, and therefore wouldn't be useful in practice.

Fortunately, in first-order logic, every statement involving ∀ can be transformed in an equivalent statement involving ∃.

In your example, the statement:

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

or "all values are > 1 and < 5" is equivalent to

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

or "there is no value that is not > 1 and < 5" which by De Morgan's laws becomes:

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

or "there is no value that is ≤ 1 or ≥ 5"

The latter can be expressed in MongoDB in many ways, for example:

> 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 ] }
自此以后,行同陌路 2024-11-15 02:25:17

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

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

You'll sacrifice speed, but you could use a JavaScript expression, either passed directly to find() or to $where.

You'd be able to loop through the elements in your array and only return true if all of them satisfied your condition.

云仙小弟 2024-11-15 02:25:17

该线程

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

解释了您的选项。

正如“chx”所写:这是不可能的。现在您已经了解了 $all 和 $or 运算符的功能。这就是您从 MongoDB 所拥有和获得的全部 - 不多也不少。

The thread

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

explains your options.

As 'chx' wrote: it is not possible. You now know the functionality of the $all and $or operators. That's all you have and get from MongoDB - nothing more, nothing less.

放飞的风筝 2024-11-15 02:25:17

据我所知,目前 MongoDB 还无法做到这一点。

编辑:我纠正了。有可能它只是不可索引,所以对我来说它属于“不可能”的领域。看看下面哪里。您还可以映射减少。这些就像 MongoDB 中的“出狱”卡,但与通常的情况一样,这些卡与真正的操作员相比存在严重的缺点。

This is not possible with MongoDB AFAIK right now.

Edit: I stand corrected. It is possible it's just not indexable so it falls the 'impossible' territory' for me. See where below. You can also map reduce. These are like the "get out of jail" cards in MongoDB but as usual with those cards, there are severe disadvantages compared to a real operator.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文