Mongodb对数组元素聚合ifNull

时间:2018-01-11 19:34:27

标签: mongodb

我有以下数据集:

{ 
    patientId: 228,
    medication: {
        atHome : [
        {
            "drug" : "tylenol", 
            "start" : "3", 
            "stop" : "7"
        }, 
        {
            "drug" : "advil", 
            "start" : "0", 
            "stop" : "2"
        }, 
        {
            "drug" : "vitaminK", 
            "start" : "0", 
            "stop" : "11"
        }
        ], 
    }
}

当我执行以下聚合时,一切看起来都很棒。

db.test01.aggregate(
[
    {$match: {patientId: 228}},
    {$project: {
        patientId: 1,
        "medication.atHome.drug": 1
        }
    },
]);

结果(正是我想要的):

{ 
"_id" : ObjectId("5a57b7d17af6772ebf647939"), 
"patientId" : NumberInt(228), 
"medication" : {
    "atHome" : [
        {"drug" : "tylenol"}, 
        {"drug" : "advil"}, 
        {"drug" : "vitaminK"}
    ]}
}

然后我们想添加ifNull来将空值更改为默认值,但是这会破坏结果。

db.test01.aggregate(
[
    {$match: {patientId: 228}},
    {$project: {
         patientId: {$ifNull: ["$patientId", NumberInt(-1)]},
         "medication.atHome.drug": {$ifNull: ["$medication.atHome.drug", "Unknown"]}
        }
    },
]);

ifNull的结果(不是我希望的):

{ 
"_id" : ObjectId("5a57b7d17af6772ebf647939"), 
"patientId" : NumberInt(228), 
"medication" : {
    "atHome" : [
        {"drug" : ["tylenol", "advil", "vitaminK"]}, 
        {"drug" : ["tylenol", "advil", "vitaminK"]}, 
        {"drug" : ["tylenol", "advil", "vitaminK"]}, 
    ]}
}

我缺少什么或不理解?

1 个答案:

答案 0 :(得分:0)

要将数组元素的文档属性设置为默认值,您需要$unwind数组,然后检查 null group >。这是查询:

db.test01.aggregate([
  // unwind to evaluete the array elements
  {$unwind: "$medication.atHome"},
  {$project: {
               patientId: {$ifNull: ["$patientId", -1]},
               "medication.atHome.drug": {$ifNull: ["$medication.atHome.drug", "Unknown"]}
             }
  },
  // group to put atHome documents to an array again
  {$group: {
             _id: {_id: "$_id", patientId: "$patientId"},
             "atHome": {$push: "$medication.atHome" }
           }
  },
  // project to get a document of required format
  {$project: {
               _id: "$_id._id",
               patientId: "$_id.patientId",
               "medication.atHome": "$atHome"
             }
  }
])

<强>更新 还有另一个更简洁的查询来实现同样的目标。它使用map运算符来计算每个数组元素,因此不需要展开。

db.test01.aggregate([
  {$project:
    {
      patientId: {$ifNull: ["$patientId", -1]},
      "medication.atHome": {
                             $map: {
                                     input: "$medication.atHome",
                                     as: "e",
                                     in: { $cond: {
                                                    if: {$eq: ["$$e.drug", null]},
                                                    then: {drug: "Unknown"},
                                                    else: {drug: "$$e.drug"}
                                                  }
                                         }
                                   }
                           }
    }
  }
])