如何在分组时使用$ cond检查同一数组中的空值进行聚合操作

时间:2017-04-12 06:09:45

标签: mongodb mongodb-query aggregation-framework

这是我的文件,

{
  "_id": "58aecaa3758fbff4176db088",
  "actualEndDate": "2017-02-27T00:00:00.000Z",
  "Details": [
    {         
      "projectId": "58a585f6758fbff4176dadb9",
    }
  ]
},
{
  "_id": "58aecac8758fbff4176db08b",
  "actualEndDate": "2017-03-12T00:00:00.000Z",
  "Details": [
    {         
      "projectId": "58a585f6758fbff4176dadb9",
    }
  ]
},
{
  "_id": "58aecac8758fbff4176db08c",
  "actualEndDate": null,
  "Details": [
    {         
      "projectId": "58a585f6758fbff4176dadb9",
    }
  ]
}

我需要对这些进行分组,在我的查询中,我需要找到" actualEndDate"的$max只有当所有" actualEndDate"字段不为空。

我尝试过这样的事情,

{ 
    $group: 
           {
              _id: '$Details.projectId',
              actualEndDate: 
                   { 
                     $cond: { 
                             if: { $ne: [ $actualEndDate, null] }, 
                             then: $actualEndDate, else: null
                            }
                   }
            }
}

这样我就能得到预期的结果,比如

{
   "projectId": "58a585f6758fbff4176dadb9",
   "actualEndDate": null,
}

如果样本不包含{ "_id": "58aecac8758fbff4176db08c" }记录,那么我希望结果actualEndDate为其他两个文档的最大值

{
   "projectId": "58a585f6758fbff4176dadb9",
   "actualEndDate": "2017-03-12T00:00:00.000Z",
}

感谢任何帮助。

1 个答案:

答案 0 :(得分:3)

您可以$sort actualDate字段,$unwind您的Details数组,然后$group仅采用$first日期将确保这是最近的日期:

db.data.aggregate([{
    $sort: {
        "actualEndDate": -1
    }
}, {
    $unwind: "$Details"
}, {
    $group: {
        _id: "$Details.projectId",
        actualEndDate: {
            $first: "$actualEndDate"
        }
    }
}]);

如果要为指定的date至少有一个日期为空,则返回空projectId,以下内容将完成此任务:

db.data.aggregate([{
    $sort: {
        "actualEndDate": -1
    }
}, {
    $unwind: "$Details"
}, {
    $group: {
        _id: "$Details.projectId",
        dates: {
            $push: "$actualEndDate"
        }
    }
}, {
    $project: {
        projectId: "$_id",
        actualEndDate: {
            $cond: {
                if: {
                    $setIsSubset: [
                        [null], "$dates"
                    ]
                },
                then: null,
                else: { $arrayElemAt: ["$dates", 0] }
            }
        }
    }
}]);

我们的想法是$push将所有日期转换为新数组,并在数组中发现null时进行投影以返回null,否则返回数组的第一个元素(使用在第一阶段排序的值)