检索与$ group aggregation

时间:2017-02-06 18:31:29

标签: mongodb mongodb-query

所以我希望将我的收藏中的文档分组到特定字段,并且对于每个组的输出结果,我希望包含以下内容:

  1. 组中与特定查询匹配的所有文档的计数(即满足某些表达式的文档计数{" $ Property":" Value"})
  2. 组中的文档总数
  3. (奖励,因为我怀疑这不容易实现)与$ min / $ max累加器对应的文档的属性
  4. 我对用于在mongo中查询的语法很新,并且不太了解它是如何工作的,但经过一些研究后,我设法将其归结为以下查询(请注意,我目前正在使用3.0.12版本用于我的mongo db,但我相信我们会在几个月后升级):

    db.getCollection('myCollection').aggregate(
        [
            {
                $group: {
                    _id: {
                        GroupID: "$GroupID", 
                        Status: "$Status"
                    }, 
                    total: { $sum: 1 }, 
                    GroupName: { $first: "$GroupName" }, 
                    EarliestCreatedDate: { $min: "$DateCreated" }, 
                    LastModifiedDate: { $max: "$LastModifiedDate" }
                }
            }, 
            {
                $group: {
                    _id: "$_id.GroupID", 
                    Statuses: {
                        $push: {
                            Status: "$_id.Status", 
                            Count: "$total"
                        }
                    }, 
                    TotalCount: { $sum: "$total" }, 
                    GroupName: { $first: "$GroupName" }, 
                    EarliestCreatedDate: { $min: "$EarliestCreatedDate" }, 
                    LastModifiedDate: { $max: "$LastModifiedDate" }
                }
            }
        ]
    )
    

    基本上我要检索的是Count for specific Status值,并将它们投影到一个最终结果文档中,如下所示:

    {
        GroupName, 
        EarliestCreatedDate, 
        EarliestCreatedBy, 
        LastModifiedDate, 
        LastModifiedBy, 
        TotalCount,
        PendingCount, 
        ClosedCount
    }
    

    PendingCount和ClosedCount是每个组中具有Pending / Closed状态的文档总数。我怀疑我需要使用带有其他表达式的$ project来提取这个值,但是我并不能很好地理解聚合管道以便解决这个问题。

    EarliestCreatedBy和LastModifiedBy也是分别创建/修改与EarliestCreatedDate和LastModifiedDate相对应的文档的用户。正如我所提到的,我认为检索这些值会增加另一层复杂性,所以如果没有实际的解决方案,我愿意放弃这个要求。

    非常感谢任何建议/提示。

1 个答案:

答案 0 :(得分:1)

您可以尝试以下聚合阶段。

$group

为每个TotalCount计算所有必要的计数PendingCountClosedCountGroupID

分别为$min$max计算EarliestCreatedDateLastModifiedDate,并pushCreatedByLastModifiedBy的所有字段稍后进行比较以获取EarliestCreatedBy {每个LastModifiedBy

{1}}和GroupID

$project

投放所有响应字段

$filter EarliestCreatedDateCreatedByLastModifiedBy$map数据CreatedBy的匹配EarliestCreatedBy$arrayElemAtLastModifiedBy将数组转换为object。

计算db.getCollection('myCollection').aggregate( [{ $group: { _id: "$GroupID", TotalCount: { $sum: 1 }, PendingCount: { $sum: { $cond: { if: { $eq: ["Status", "Pending"] }, then: 1, else: 0 } } }, ClosedCount: { $sum: { $cond: { if: { $eq: ["Status", "Closed "] }, then: 1, else: 0 } } }, GroupName: { $first: "$GroupName" }, EarliestCreatedDate: { $min: "$DateCreated" }, LastModifiedDate: { $max: "$LastModifiedDate" }, CreatedByLastModifiedBy: { $push: { CreatedBy: "$CreatedBy", LastModifiedBy: "$LastModifiedBy", DateCreated: "$DateCreated", LastModifiedDate: "$LastModifiedDate" } } } }, { $project: { _id: 0, GroupName: 1, EarliestCreatedDate: 1, EarliestCreatedBy: { $arrayElemAt: [{ $map: { input: { $filter: { input: "$CreatedByLastModifiedBy", as: "CrBy", cond: { "$eq": ["$EarliestCreatedDate", "$$CrBy.DateCreated"] } } }, as: "EaCrBy", in: { "$$EaCrBy.CreatedBy" } } }, 0] }, LastModifiedDate: 1, LastModifiedBy: { $arrayElemAt: [{ $map: { input: { $filter: { input: "$CreatedByLastModifiedBy", as: "MoBy", cond: { "$eq": ["$LastModifiedDate", "$$MoBy.LastModifiedDate"] } } }, as: "LaMoBy", in: { "$$LaMoBy.LastModifiedBy" } } }, 0] }, TotalCount: 1, PendingCount: 1, ClosedCount: 1 } }] )

的类似步骤
$filter

版本更新< 3.2

false在您的版本中也不可用。以下是等效的。

比较逻辑是相同的,并创建一个数组,其中每个非匹配条目的值为LastModifiedBy$setDifference

下一步是使用[false]将先前的数组值与数组LastModifiedBy: { $setDifference: [{ $map: { input: "$CreatedByLastModifiedBy", as: "MoBy", in: { $cond: [{ $eq: ["$LastModifiedDate", "$$MoBy.LastModifiedDate"] }, "$$MoBy.LastModifiedBy", false ] } } }, [false] ] } 进行比较,后者返回仅存在于第一组中的元素。

$unwind

$project阶段之后添加{$unwind:"$LastModifiedBy"} 阶段以更改为对象

EarliestCreatedBy

计算{{1}}

的类似步骤