使用mongoDB将嵌入式文档与父字段进行比较 [英] Compare embedded document to parent field with mongoDB
问题描述
请考虑以下集合,其中父文档具有值为100000
的amount
字段,并且存在具有相同字段amount
和相同值的嵌入式文档数组.
Consider the following collection, where the parent document has a amount
field with the value 100000
and there's an embedded array of documents with the same field amount
and the same value.
{
"_id" : ObjectId("5975ce5f05563b6303924914"),
"amount" : 100000,
"offers" : [
{
"amount": 100000
}
]
}
有什么方法可以匹配具有至少一个嵌入式文档offer
且与父对象具有相同数量的所有对象?
Is there any way to match all objects that has at least one embedded document offer
with the same amount as the parent?
例如,如果我对此进行查询,它就可以正常工作:
If I for example query this, it works just fine:
find({ offers: { $elemMatch: { loan_amount: 100000 } } })
但是我不知道我要组装的实际查询中的实际值100000
,我需要为父文档数量字段使用一个变量.像这样的东西.
But I don't know the actual value 100000
in the real query I'm trying to assemble, I would need to use a variable for the parent documents amount field. Something like this.
find({ offers: { $elemMatch: { loan_amount: "parent.loan_amount" } } })
感谢您的任何建议.我希望使用$eq
或$elemMatch
进行此操作,并避免发生聚集,但这也许是不可能的.
Thankful for any suggestions. I was hoping to do this with $eq
or $elemMatch
, and to avoid aggregates, but maybe it's not possible.
谢谢!
推荐答案
标准查询无法比较"文档中的值.这实际上是您使用.aggregate()
和 $redact
:
Standard queries cannot "compare" values in documents. This is actually something you do using .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"
}
}}
])
在这里,我们使用 $filter
进行比较父文档中"amount"
的值与数组中的值相同.如果至少一个等于",则我们"$$KEEP"
该文档,否则我们"$$PRUNE"
Here we use $filter
to compare the values of "amount"
in the parent document to those within the array. If at least one is "equal" then we "$$KEEP"
the document, otherwise we "$$PRUNE"
In most recent versions, we can shorten that using $indexOfArray
.
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$ne": [
{ "$indexOfArray": [ "$offers.amount", "$amount" ] },
-1
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
If you actually only wanted the "matching array element(s)" as well, then you would add a $filter
in projection:
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" ] }
}
}
}}
])
但是主要原则当然是减少"返回给仅的那些文档的数量,这些文档实际上是符合条件的第一"优先级.否则,您只是在进行不必要的计算而浪费时间和资源,因为以后您将放弃这些结果.
But the main principle is of course to "reduce" the number of documents returned to only those that actually match the condition as a "first" priority. Otherwise you are just doing unnecessary calculations and work that is taking time and resources, for results that you later would discard.
因此优先考虑过滤",然后优先考虑重塑".
So "filter" first, and "reshape" second as a priority.
这篇关于使用mongoDB将嵌入式文档与父字段进行比较的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!