1

我有访问用户的数据库,其中包含这样的 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 data API没有这样的,至少我在参考中没有找到它。

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

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

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

任何帮助表示赞赏。

4

1 回答 1

3

我将在“一击”中回答这个问题,因此我不会解决您的“$project”问题,而是在这里建议有更好的方法。

操作员将$addToSet创建您要求添加到其中的元素的“唯一”数组(或“集合”)。然而,它本身基本上是另一种形式,$group不同之处在于元素被添加到结果中的“数组”(或“集合”)中。

这对于可伸缩性来说是“坏的”,因为您的潜在问题是“集合”实际上超过了文档大小的 BSON 限制。也许现在还没有,但谁知道你现在写的代码在十年后会做什么。

因此,因为$group实际上是同一件事,并且您还需要“两个”管道阶段来获得“不同”计数,然后只需要“两个”$group阶段来代替:

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

作为外壳等价于:

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

这是一个简单的代码,它更“可扩展”,因为单个“user_id”值首先包含在管道中的单独文档中。因此,“第二个” $group(用 $size 代替 $project )“计算”在第一个分组键中已经确定的不同数量。

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

于 2015-07-24T11:15:18.117 回答