展开后的组元素并忽略重复 - MongoDB聚合

时间:2017-11-20 10:20:59

标签: spring mongodb aggregation-framework spring-data-mongodb

我使用聚合来展开一个数组,并按数组的每个元素进行分组以总结一些相应的值。

我的收藏就像:

/* 1 */
{
    "_id" : ObjectId("59ce411c2708c97154d1319b"),
    "sourceMediumPath" : [ 
        {
            "nodeValue" : "(direct) / (none)"
        }, 
        {
            "nodeValue" : "(direct) / (none)"
        }
    ],
    "totalConversions" : 1,
    "totalConversionValue" : 171.6,
}

/* 2 */
{
    "_id" : ObjectId("59ce411c2708c97154d136a0"),
    "sourceMediumPath" : [ 
        {
            "nodeValue" : "google / cpc"
        }, 
        {
            "nodeValue" : "(direct) / (none)"
        }, 
        {
            "nodeValue" : "google / cpc"
        }
    ],
    "totalConversions" : 1,
    "totalConversionValue" : 151.8,
}

我想通过sourceMedium.nodeValue和sum' totalConverions'进行分组。和' totalConversionValue'没有重复的要素。

例如,通过使用展开,分组和求和:

aggregation = Aggregation.newAggregation(
                    Aggregation.unwind("sourceMediumPath"),
                    Aggregation.group("sourceMediumPath.nodeValue")
                            .sum("totalConversions").as(Variables.TOTAL_CONNVERSIONS)
                            .sum("TotalConversionValue").as(Variables.TOTAL_CONVERSION_VALUE),

                    Aggregation.project("sourceMediumPath.nodeValue")
                            .andInclude(Variables.TOTAL_CONNVERSIONS, Variables.TOTAL_CONVERSION_VALUE)

我得到" nodeValue" :"(直接)/(无)" TotalConversions的总和等于3,而#34; google / cpc"一个Sum等于1.因为它在执行展开操作时复制了totalConversions和totalConversions。

有任何解决方案可以忽略重复,每个文档只有一个值。

我该怎么做?

1 个答案:

答案 0 :(得分:0)

您可以使用$addField添加$unwind阶段以使用$setIntersection创建一系列唯一值,然后将此字段展开,如下所示:

db.collection.aggregate( [
    { $addFields: {
        sourceMediumUniquePath: { $setIntersection: [ 
            "$sourceMediumPath", 
            "$sourceMediumPath" 
        ] }
    } },
    { $unwind: "$sourceMediumUniquePath" },
    ... rest of the pipeline ...
])

<强>更新

如果不支持$addFields,则可以将其替换为$project阶段。唯一的缺点是您需要列出以后阶段所需的所有字段。 E.g:

db.collection.aggregate( [
    { $project: {
        sourceMediumUniquePath: { $setIntersection: [ 
            "$sourceMediumPath", 
            "$sourceMediumPath" 
        ] },
        totalConversions: 1,
        totalConversionValue: 1
    } },
    { $unwind: "$sourceMediumUniquePath" },
    ... rest of the pipeline ...
])