如何使用主文档中的值查询子文档数组

How to query subdocument array using value in main document

我有一个具有一些属性的文档,其中一个属性是一个子文档数组,我想查找文档并将主文档中的 属性 与子文档中的 属性 进行比较文档数组

下面是文档的一个例子

{
"_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 {Year: OptimalYear}

中使用 OptimalYear 的值

您不能使用标准查询来执行此操作,或者大多数人实际要求的是在处理更新时引用文档中字段的值。没有允许在这些查询中引用字段值的语法。

您可以在聚合框架中执行此操作。自 MongoDB 2.6 以来的现代版本具有 $redact 管道阶段,它有一个很好的处理方式:

db.collection.aggregate([
    { "$redact": {
        "$cond": {
            "if": {
                "$eq": [
                    { "$ifNull": [ "$Year", "$$ROOT.OptimalYear" ] },
                    "$$ROOT.OptimalYear"
                ]
            },
            "then": "$$DESCEND",
            "else": "$$PRUNE"
        }
    }}
])

这基本上评估 $cond 条件或三元语句以查看值实际匹配的位置,然后您将保留该元素。否则当前文档级别将被删除。

$ifNull is there along with references to $$ROOT因为这是递归遍历的结构。例如,文档顶部没有 "Year" 字段,因此比较被替换为 "OptimalYear" 值。与自己比较 returns 正确,但在数组中它将与存在的 "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 阶段检查空数组来做到这一点。