嵌入式阵列中嵌入式文档中的项目字段

时间:2017-01-17 10:55:55

标签: mongodb aggregation-framework

我有以下查询:

 cursor=self.postCol.aggregate([
      { "$graphLookup" : {
        "from": "pCol",
        "startWith": "$parent",
        "connectFromField": "parent",
        "connectToField": "_id",
        "as" : "parents"
        }
      },
      { "$project" : {
         "pValue": {
             "$cond": [
               { "$ne": [ "$pValue", [] ] },
               "$pValue",
               "$parents.0.pValue"
             ]
           }
         }
      }
    ])

然后给出以下记录:

{"_id": 4, parent: "", "pValue": ["d"], fieldA: 9},
{"_id": 5, parent: 4, "pValue": [], fieldA:2},
{"_id": 6, parent: 4,"pValue": [], fieldA: 9}

我应该得到:

{"_id": 4, "pValue": ["d"]}
{"_id": 5, "pValue": ["d"]}
{"_id": 6, "pValue": ["d"]}

相反,我得到:

{"_id": 4, "pValue": ["d"]}
{"_id": 5, "pValue": []}
{"_id": 6, "pValue": []}

由于某些我不理解的原因,$parents.0.pValue没有返回正确的值。如何在父数组的第一个元素中选择pValue字段?

我想使用{"$arrayElemAt": ["$parents",0]}会给我嵌入的文档,但是我怎样才能从中获取一个字段?

2 个答案:

答案 0 :(得分:2)

您可以使用$switch运算符和$let运算符来$project您的字段。

$let变量运算符允许您为变量赋值,该变量可用于" in"表达式,如我的其他答案here所示。

使用$switch运算符,我们可以perform very clean case-statement.

db.postCol.aggregate([
    { "$graphLookup": { 
        "from": "postCol",  
        "startWith": "$parent",  
        "connectFromField": "parent", 
        "connectToField": "_id",   
        "as" : "parents"           
    }}, 
    { "$project": { 
        "pValue": { 
            "$switch": { 
                "branches": [ 
                    { "case": { "$gt": [ { "$size": "$pValue"}, 0 ] },
                    "then": "$pValue" }
                ], 
                "default": { 
                    "$let": { 
                        "vars": { "p": { "$arrayElemAt": [ "$parents", 0 ] }}, 
                        "in": "$$p.pValue" 
                    }
                }
            }
        }
    }}
])

答案 1 :(得分:1)

您可以使用$let运算符替换下面的else条件。

 {
    $let: {
        vars: {
            obj: {
                "$arrayElemAt": ["$parents", 0]
            }
        },
        in: "$$obj.pValue"
    }
 }