web-dev-qa-db-fra.com

MongoDB - Détruire un tableau en utilisant l'agrégation et supprimer les doublons

Je décompresse un tableau à l'aide de la structure d'agrégation MongoDB. Le tableau contient des doublons et je dois ignorer ces doublons tout en effectuant un regroupement supplémentaire.

Comment puis-je y arriver?

39
l a s

vous pouvez utiliser $ addToSet pour le faire:

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

Il est difficile de vous donner une réponse plus précise sans voir votre requête réelle.

42
Roman Pekar

Vous devez utiliser $ addToSet, mais vous devez d'abord grouper par _id, sinon vous obtiendrez un élément par élément dans la liste.

Imaginez une collection qui affiche des documents comme celui-ci:

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

Imaginez que vous souhaitiez calculer le tag le plus courant par auteur. Vous feriez une requête agrégée comme ça:

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}
    }}
])

De cette façon, vous obtiendrez des documents comme celui-ci:

{
     _id: {
         author: "Enrique Coslado", 
         tags: "lorem"
     },
     count: 1
}
24
Enrique Coslado

Les réponses précédentes sont correctes, mais vous pouvez simplifier la procédure $unwind -> $group -> $unwind ..__ Vous pouvez utiliser $addFields + $reduce pour transmettre au pipeline le tableau filtré contenant déjà des entrées uniques, puis $unwind une seule fois.

Exemple de document:

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

Question:

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}
    }}
])
0
cephuo