MongoDB - 使用聚合展开数组并删除重复项

时间:2013-09-14 17:22:50

标签: mongodb

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

我怎样才能做到这一点?

3 个答案:

答案 0 :(得分:43)

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

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

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

答案 1 :(得分:24)

你必须使用$ 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
}

答案 2 :(得分:0)

先前的回答是正确的,但是可以简化执行$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}
    }}
])