使用MongoDB聚合框架按数组长度分组

10

我有一个收藏品,看起来像这样:

{
    "_id": "id0",
    "name": "...",
    "saved_things": [
        { ... },
        { ... },
        { ... },
    ]
}
{
    "_id": "id1",
    "name": "...",
    "saved_things": [
        { ... },
    ]
}
{
    "_id": "id2",
    "name": "...",
    "saved_things": [
        { ... },
    ]
}
我希望使用MongoDB的聚合框架来生成一个直方图结果,告诉我有多少用户有一个特定数量的“saved_things”。例如,对于上面的数据集,它可以返回类似以下内容的结果:
{ "_id": 1, "count": 2 },
{ "_id": 3, "count": 1 }

我尝试了像以下这样的不同聚合函数的组合,但没有一个能够正确地解决问题。(我感觉自己做错了什么。)

collection.aggregate([
    { $unwind: "$saved_things" },
    { $group: "$_id", count: { $sum: 1 } } },
    { $group: "$count", number: { $sum: 1 } } },
    { $sort: { number: -1 } }
], function(err, result) {
    console.log(result);
});

使用Mongo的聚合框架可以实现这个吗,还是用MapReduce函数更好?


你的意思是“有多少用户有一定数量的saved_things subcollection”?给定一个“saved_thing”,你想知道哪些用户有“saved_things”,以及有多少个?就是这样吗? - Miguel Cartagena
嗯,我的措辞好像有点混乱,对不起! 我认为示例输出最能描述我要寻找的内容,但我会再次尝试描述一下。我想获得集合中每个用户“saved_things”对象的数量,并聚合该计数的频率。 这是为了生成用户“saved_things”数量的直方图(如果有意义)。如果还有任何不清楚的地方,请告诉我。 - Steve Gattuso
2个回答

9

好的,明白了!我们来说一下聚合管道的基本原理:

{
    $unwind: "$saved_things"
},
{
    $group: {
        _id: "$_id",
        size: {
            $sum: 1
        }
    }
},
{
    $group: {
        _id: "$size",
        frequency: {
            $sum: 1
        }
    }
},
{
    $project: {
        size: "$_id",
        frequency: 1,
        _id: 0
    }
}

解开 saved_things 数组,然后按文档 _id 进行分组并计数,这样我们就可以得到数组的大小。现在很容易,按 size 进行分组并计算频率。使用 project 将 _id 字段重命名为 size

看起来非常接近。这是我的输出结果:https://gist.github.com/stevenleeg/2b1a2ee9c5400f5f3089 - Steve Gattuso
开个玩笑!我输出的是 results 而不是 result,这导致了问题。唯一看到的不太对的地方是没有频率为0的数据。有什么可以做的吗? - Steve Gattuso
我不相信这个聚合会为长度为零的数组的文档包括频率值。曾经困惑了一分钟,因为我的频率总数与我的特定集合计数不匹配。 - steveinatorx

3
你可以使用 $size 键。 示例。
query :

[{ 
   $group: {
     _id:{$size:'$saved_things'},
     total: { $sum: 1 },
   }
}]

output:
[{ _id: 4, total: 2 }]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接