【问题标题】:Group Elements after unwind and ignore duplication - MongoDB Aggregation展开后对元素进行分组并忽略重复 - MongoDB Aggregation
【发布时间】:2017-11-20 10:20:59
【问题描述】:

我使用聚合来展开一个数组,并按数组的每个元素分组以求和一些对应的值。

我的收藏是这样的:

/* 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 进行分组,并对“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”:“(direct)/(none)”,TotalConversions 的总和等于 3,而“google / cpc”的总和等于 1。因为它在执行展开操作时重复了 totalConversions 和 totalConversions .

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

我该怎么做?

【问题讨论】:

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


    【解决方案1】:

    您可以在 $unwind 阶段添加 $addField 以使用 $setIntersection 创建一个唯一值数组,并按如下方式展开此字段:

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

    更新:

    如果$addFields不支持,可以用$projectstage代替。唯一的缺点是您需要列出以后需要的所有字段。例如:

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

    【讨论】:

    • 非常感谢,我想到了这一点,但我没有把它当作技术。我是Mongodb聚合的新玩家,你如何使用Java管道执行它,我在聚合中找不到$addFields管道
    • 请查看没有$addField阶段的更新。我对spring没有太多经验,但似乎可以在投影阶段添加字段:docs.spring.io/spring-data/mongodb/docs/current/reference/html/…必须类似于and("sourceMediumPath").intersects("sourceMediumPath").as("sourceMediumUniquePath")
    • 是的,确实!非常感谢 spring 数据支持 Intersection 中的投影:Aggregation.project(X,Y,Z).and(sourceMediumPath).intersectsArrays(sourceMediumPath).as("Intersect") .. 我将发布解决方案一旦它工作。 . 谢谢你的帮助
    【解决方案2】:

    在 Spring Data 中,聚合投影管道中的 intersectarrays 通过应用与数组相同的交集来完成这项工作。

    aggregation = Aggregation.newAggregation(
                   Aggregation.project().and("sourceMediumPathnodeValue").intersectsArrays("sourceMediumPathnodeValue").as("Intersection").andInclude(...),
                        Aggregation.unwind("Intersection"),
                        Aggregation.group("Intersection")
                                .sum("totalConversions").as("totalConversions")
                                .sum("TotalConversionValue").as(TotalConversionValue"),
                        Aggregation.project("sourceMediumPath.nodeValue")
                                .andInclude("totalConversions", TotalConversionValue")
    
                            new OutOperation("OutputCollection")
                    ).withOptions(Aggregation.newAggregationOptions().allowDiskUse(true).build());
    

    非常感谢您的帮助

    【讨论】:

      猜你喜欢
      • 2021-01-05
      • 2021-09-27
      • 1970-01-01
      • 2013-09-24
      • 1970-01-01
      • 1970-01-01
      • 2011-07-01
      • 1970-01-01
      • 2016-08-28
      相关资源
      最近更新 更多