43

我正在使用 MongoDB 聚合框架展开一个数组,并且该数组有重复项,我需要在进一步分组时忽略这些重复项。

我怎样才能做到这一点?

4

3 回答 3

49

您可以使用$addToSet来执行此操作:

db.users.aggregate([
  { $unwind: '$data' },
  { $group: { _id: '$_id', data: { $addToSet: '$data' } } }
]);

如果没有看到您的实际查询,很难给您更具体的答案。

于 2013-09-14T17:28:05.243 回答
28

您必须使用 $addToSet,但首先您必须按 _id 分组,因为如果不这样做,您将在列表中的每个项目中获得一个元素。

想象一个包含这样文档的集合帖子:

{
     body: "Lorem Ipsum...", 
     tags: ["stuff", "lorem", "lorem"],
     author: "Enrique Coslado"
}

想象一下,您想计算每个作者最常用的标签。你会做一个这样的聚合查询:

db.posts.aggregate([
    {$project: {
        author: "$author", 
        tags: "$tags", 
        post_id: "$_id"
    }}, 

    {$unwind: "$tags"}, 

    {$group: {
        _id: "$post_id", 
        author: {$first: "$author"}, 
        tags: {$addToSet: "$tags"}
    }}, 

    {$unwind: "$tags"},

    {$group: {
        _id: {
            author: "$author",
            tags: "$tags"
        },
        count: {$sum: 1}
    }}
])

这样你会得到这样的文件:

{
     _id: {
         author: "Enrique Coslado", 
         tags: "lorem"
     },
     count: 1
}
于 2014-12-13T14:12:51.673 回答
3

以前的答案是正确的,但做的过程$unwind -> $group -> $unwind可以简化。您可以使用$addFields+$reduce将已包含唯一条目的过滤数组传递给管道,然后$unwind只传递一次。

示例文档:

{
     body: "Lorem Ipsum...", 
     tags: [{title: 'test1'}, {title: 'test2'}, {title: 'test1'}, ],
     author: "First Last name"
}

询问:

db.posts.aggregate([
    {$addFields: {
        "uniqueTag": {
            $reduce: {
                input: "$tags",
                initialValue: [],
                in: {$setUnion: ["$$value", ["$$this.title"]]}
            }
        }
    }}, 

    {$unwind: "$uniqueTag"}, 

    {$group: {
        _id: {
            author: "$author",
            tags: "$uniqueTag"
        },
        count: {$sum: 1}
    }}
])
于 2018-07-31T12:00:50.283 回答