Ste*_*nno 5 mongodb mongodb-query aggregation-framework
考虑以下集合,其中父文档有一个amount
带有值的字段,100000
并且有一个具有相同字段amount
和相同值的嵌入文档数组。
{
"_id" : ObjectId("5975ce5f05563b6303924914"),
"amount" : 100000,
"offers" : [
{
"amount": 100000
}
]
Run Code Online (Sandbox Code Playgroud)
}
有什么方法可以匹配至少一个嵌入文档offer
与父文档数量相同的所有对象?
例如,如果我查询这个,它工作得很好:
find({ offers: { $elemMatch: { loan_amount: 100000 } } })
Run Code Online (Sandbox Code Playgroud)
但是我不知道100000
我尝试组合的实际查询中的实际值,我需要为父文档金额字段使用一个变量。像这样的东西。
find({ offers: { $elemMatch: { loan_amount: "parent.loan_amount" } } })
Run Code Online (Sandbox Code Playgroud)
感谢您的任何建议。我希望用$eq
or做到这一点$elemMatch
,并避免聚合,但也许这是不可能的。
谢谢!
标准查询无法“比较”文档中的值。这实际上是您使用.aggregate()
and所做的事情$redact
:
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$gt": [
{ "$size": {
"$filter": {
"input": "$offers",
"as": "o",
"cond": { "$eq": [ "$$o.amount", "$amount" ] }
}
}},
0
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Run Code Online (Sandbox Code Playgroud)
这里我们用来$filter
将父文档中的值"amount"
与数组中的值进行比较。如果至少有一个“相等”,那么我们就是"$$KEEP"
文档,否则我们"$$PRUNE"
在最新版本中,我们可以使用 来缩短它$indexOfArray
。
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$ne": [
{ "$indexOfArray": [ "$offers.amount", "$amount" ] },
-1
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Run Code Online (Sandbox Code Playgroud)
如果您实际上只想要“匹配的数组元素”,那么您将添加一个$filter
in 投影:
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$gt": [
{ "$size": {
"$filter": {
"input": "$offers",
"as": "o",
"cond": { "$eq": [ "$$o.amount", "$amount" ] }
}
}},
0
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}},
{ "$project": {
"amount": 1,
"offers": {
"$filter": {
"input": "$offers",
"as": "o",
"cond": { "$eq": [ "$$o.amount", "$amount" ] }
}
}
}}
])
Run Code Online (Sandbox Code Playgroud)
但主要原则当然是“减少”返回的文档数量,只返回那些真正符合条件的文档作为“第一”优先级。否则,您只是在进行不必要的计算和工作,这些工作需要花费时间和资源,而您稍后会丢弃结果。
因此,优先考虑的是首先“过滤”,然后“重塑”。