我有一个具有一些属性的文档,其中一个属性是子文档数组,我想查找文档并将主文档中的属性与子文档数组中的属性进行比较
以下是文档的示例
{
"_id" : ObjectId("54bb897d52a8a302ecafeb03"),
“Contract" : “ABCDE",
“OptimalYear" : 2012,
"Results" : [
{
"Year" : 2011,
"Risk" : 1114
},
{
"Year" : 2012,
"Risk" : 1226
},
{
"Year" : 2013,
"Risk" : 1385.5
}
]
}
我能做到
db.CC.find({
Contract: "Jan",
Result: {
$elemMatch: {
Year: 2012
}
}
})
但是如何在$ elemMatch中使用OptimalYear的值{Year:OptimalYear}
答案 0 :(得分:1)
您不能使用标准查询执行此操作,或者大多数人实际要求的是在处理更新时引用文档中字段的值。没有语法允许在这些查询中引用字段值。
您可以使用聚合框架执行此操作。自MongoDB 2.6以来的现代版本具有$redact
管道阶段,它有一个很好的处理方式:
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$eq": [
{ "$ifNull": [ "$Year", "$$ROOT.OptimalYear" ] },
"$$ROOT.OptimalYear"
]
},
"then": "$$DESCEND",
"else": "$$PRUNE"
}
}}
])
这基本上会评估$cond
条件或三元语句,以查看值实际匹配的位置,然后保留元素。否则,将删除当前文档级别。
$ifNull
与$$ROOT
的引用一起存在,因为这是通过结构的递归。例如,文档顶部没有“Year”字段,因此比较将替换为“OptimalYear”值。与你自己比较会返回true,但是在数组中它会与存在的“Year”进行比较。
在早期版本中,仍然可以这样做,但它确实需要更多工作,因此不是最佳方式:
db.collection.aggregate([
{ "$unwind": "$Results" },
{ "$project": {
"Contract": 1,
"OptimalYear": 1,
"Results": 1,
"matched": { "$eq": [ "$Results.Year", "$OptimalYear" ] }
}},
{ "$match": { "matched": true } },
{ "$group": {
"_id": "$_id",
"Contract": { "$first": "$Contract" },
"OptimalYear": { "$first": "$OptimalYear" },
"Results": { "$push": "$Results" }
}}
])
不完全相同,因为它过滤掉了没有完全匹配的文档,您也可以在之前的版本中添加额外的$match
阶段检查空数组。