我找到了比较同一MongoDB集合中的差异文档中数组之间的值的方法,但是如何在一个文档中按照索引比较同一数组中的元素?这是有问题的条目:
{ "_id" : ObjectId("1"), "arr" : [ { "int" : 100 }, { "int" : 10 } ] }
我有一个包含大量这些条目的集合(当然在这里简化),我想查询集合,检查每个条目,以及arr[0].int > arr[1].int
是否返回这些文档。更好的是具有用于确定index 1
处的元素与index 0
处的元素的差异的逻辑。所以在这种情况下,例如,index 1 is 10 times less than index 0
以下工作用于查询mongoDoc中的元素是否大于给定值:
db.collection.find( { "arr.0.int" : { $gt: 10 }})
我玩过这个 - 但事实证明没有任何用处。 由于数据集很大 - 性能考虑因素很棒!
谢谢!
答案 0 :(得分:2)
这里的基本情况是简单地应用$redact
和$arrayElemAt
的条件来检查每个索引:
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$gt": [
{ "$arrayElemAt": ["$arr.int", 0] },
{ "$arrayElemAt": ["$arr.int", 1] }
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
这是一个特殊的管道阶段,以满足"if"
条件"then"
的方式"$$KEEP"
使用"else"
我们"$$PRUNE"
结果中的文档,否则{{1}我们db.collection.aggregate([
{ "$match": {
"$expr": {
"$gt": [
{ "$arrayElemAt": ["$arr.int", 0] },
{ "$arrayElemAt": ["$arr.int", 1] }
]
}
}}
])
来自结果。
这使用本机运算符,并且作为“高性能”,因为依赖于计算的查询将会得到。
MongoDB 3.6使用$cond
:
.find()
甚至可以在db.collection.find({
"$expr": {
"$gt": [
{ "$arrayElemAt": ["$arr.int", 0] },
{ "$arrayElemAt": ["$arr.int", 1] }
]
}
})
:
db.collection.find({
"$where": "return this.arr[0].int > this.arr[1].int"
})
自发布以来的所有版本都通过$expr
支持JavaScript评估:
.find()
但是,由于这需要为每个文档评估JavaScript表达式,因此它不像使用本机运算符那样高效。
另外,获得“比率”响应的唯一方法是使用聚合管道,该管道实际上可以“更改”返回的结果,而db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$gt": [
{ "$arrayElemAt": ["$arr.int", 0] },
{ "$arrayElemAt": ["$arr.int", 1] }
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}},
{ "$addFields": {
"ratio": {
"$divide": [
{ "$arrayElemAt": ["$arr.int", 1] },
{ "$arrayElemAt": ["$arr.int", 0] }
]
}
}}
])
查询无法做到:
{ "arr": [{ "int": 100 },{ "int": 10 }], "firstIsGreater": true }
无论如何,“计算作为条件”没有什么好处,因为除了遍历集合中的每个文档并查看它是否符合条件之外,没有其他选择。
因此,如果这是“通用逻辑”,那么您最好将其存储在文档中。即:
class UserRegistrationForm(forms.Form):
username = forms.CharField(
required = True,
label = 'Username',
max_length = 32
)
password = forms.CharField(
required = True,
label = 'Password',
max_length = 32,
widget = forms.PasswordInput()
)
然后你实际上“可以”以有效的方式使用索引进行选择。因此,当您更改文档中的内容时,应由您的应用程序逻辑来编写此条件,从而使您不需要进行此类计算。
如果您无法以这种方式进行建模和存储,那么您可以使用任何一种形式进行计算。因此,通常最好先考虑一下为什么你认为首先需要这样一个计算条件。