我有访问用户的地方,其中包含place_id和user_id像这样的db
{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(). .... ?
也许有任何方法也可以创建大小字段,比嵌套api可以使用:
Aggregation.project().and("distinctUserCount").nested( ???);
我将以"一击"的方式回答这个问题,而不是解决你的"$project"问题,我在这里建议有一个更好的方法。
$addToSet
操作符将创建一个"唯一"数组(或"集合"),其中包含您要求添加的元素。然而,它本身基本上是 $group
的另一种形式,不同的是元素在结果中被添加到"数组"(或"集合")中。
这对于可伸缩性来说是"坏的",因为这里的潜在问题是"set"实际上超过了文档大小的BSON限制。也许现在还没有,但是谁知道你现在写的代码十年后会做什么呢。
因此,由于$group
实际上是相同的事情,并且您还需要"两个"管道阶段来获得"不同"计数,那么只需"两个"$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 }
}}
]
这是一个简单的代码,它更"可扩展",因为单独的"user_id"值首先包含在管道中的单独文档中。因此,"第二个"$group
(代替带有$size的$project)"计数"已在第一个分组键中确定的不同数量。
了解局限性和缺陷,并编写好代码。