Spring数据 - 计算分组中的不同项

时间:2015-07-24 10:51:09

标签: java mongodb mongodb-query aggregation-framework spring-mongodb

我有访问地点的用户数据库,其中包含place_id和user_id,如此

{place_id : 1, user_id : 1}
{place_id : 1, user_id : 1}
{place_id : 1, user_id : 2}
{place_id : 2, user_id : 3}
{place_id : 2, user_id : 3}

我想在每个地方获得大量不同的用户。我最终关注了本地mongo聚合:

db.collection.aggregate([{
        $group: {
            _id: "$place_id",
            setOfUsers: {
                $addToSet: "$user_id"
            }
        }
    }, {
        $project: {
            distinctUserCount: {
                $size: "$setOfUsers"
            }
        }
    }])

现在我想用Spring Data实现它,现在的问题是投影中的$ size操作,因为Spring数据API没有这样的,至少我还没有在参考中找到它。

    GroupOperation group = Aggregation.group("place_id").addToSet("user_id").as("setOfUsers");
    ProjectionOperation project = Aggregation.project(). .... ?

也许有任何方法可以创建大小字段,而不是使用嵌套的api:

Aggregation.project().and("distinctUserCount").nested( ???);

感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

我将在"一次点击"中回答这个问题,而不是解决你的" $项目"问题,我在这里建议有一个更好的方法。

$addToSet运营商将创建一个"唯一的"要求添加到其中的元素的数组(或" set")。然而,它本质上是$group的另一种形式,不同之处在于元素被添加到"数组" (或"设置")在结果中。

这是"坏"对于可扩展性,因为你的潜在问题是" set"实际上超过了文件大小的BSON限制。也许它现在不行,但是谁知道你现在编写的代码将在十年内完成。

因此,$group实际上是相同的,你也需要"两个"管道阶段,以获得" distinct"数,然后只是"两个" $group代替:

    Aggregation pipeline = newAggregation(
        group(fields("place_id","user_id")),
        group("_id.place_id").count().as("distinctUserCount")
    );

作为shell的等价物:

[
    { "$group": {
        "_id": { "place_id": "$place_id", "user_id": "$user_id" }
    }},
    { "$group": {
        "_id": "$_id.place_id",
        "distinctUserCount": { "$sum": 1 }
    }}
]

这是一个简单的代码,它更具有可扩展性和#34;作为个人" user_id"值最初包含在管道中的单独文档中。因此"第二" $group(代替$ size的$项目)"计数"已在第一个分组键中确定的不同金额。

了解限制和陷阱,并编写良好的代码。