使用mongoDB将嵌入文档与父字段进行比较
考虑以下集合,其中父文档有一个值为使用mongoDB将嵌入文档与父字段进行比较,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,考虑以下集合,其中父文档有一个值为100000的amount字段,并且有一个具有相同字段amount和相同值的嵌入文档数组 { "_id" : ObjectId("5975ce5f05563b6303924914"), "amount" : 100000, "offers" : [ { "amount": 100000 } ] } 是否有任何方法可以将至少有一个嵌入文档offer的所有对象与父对象的金额匹配 例如,如果我对此进行查询,它可以正常工作: find
100000
的amount
字段,并且有一个具有相同字段amount
和相同值的嵌入文档数组
{
"_id" : ObjectId("5975ce5f05563b6303924914"),
"amount" : 100000,
"offers" : [
{
"amount": 100000
}
]
}
是否有任何方法可以将至少有一个嵌入文档offer
的所有对象与父对象的金额匹配
例如,如果我对此进行查询,它可以正常工作:
find({ offers: { $elemMatch: { loan_amount: 100000 } } })
但我不知道实际值100000
在我试图汇编的实际查询中,我需要为父文档金额字段使用一个变量。像这样的
find({ offers: { $elemMatch: { loan_amount: "parent.loan_amount" } } })
谢谢你的建议。我希望用$eq
或$elemMatch
来实现这一点,并避免聚合,但这可能是不可能的
谢谢 标准查询无法“比较”文档中的值。这实际上是您使用.aggregate()
和:
这里我们使用来比较父文档中的“amount”
值与数组中的值。如果至少有一个是“相等”的,则我们“$$KEEP”
文档,否则我们“$$PRUNE”
在最新的版本中,我们可以使用
如果您实际上也只需要“匹配数组元素”,那么您可以在投影中添加一个:
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" ] }
}
}
}}
])
但是,主要原则当然是“减少”返回到的文档数量,仅将实际符合条件的文档作为“第一”优先级。否则,您只是在做不必要的计算和工作,这需要花费时间和资源,以获得稍后将丢弃的结果
因此,首先“过滤”,然后“重塑”作为优先级。我认为自从MongoDB版本3.6以来,您实际上可以通过使用操作符的简单过滤器来实现这一点 大致如下:
find({
$expr: {
$in: [
"$amount",
"$offers.amount"
]
}
})
请参见上的一个实时示例非常感谢,如果提供文档有自己的集合并引用其他文档,会更容易些吗。这种聚合似乎需要做很多工作,我是说性能方面,将报价文档放在它自己的集合中并引用其他文档id是否更好?@stefankono“性能方面”将内容放在另一个集合中更糟糕。成本高昂。这就是为什么您首先“应该”使用MongoDB。没有“简单”的方法将一个字段与另一个字段进行比较。任何方法都有成本,关系数据库也是如此。再次感谢,我将尝试一下。我感谢你的努力,祝你有一个愉快的一天!
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" ] }
}
}
}}
])
find({
$expr: {
$in: [
"$amount",
"$offers.amount"
]
}
})