1
votes

Comment recombiner des documents déroulés?

J'ai le document suivant:

db.getCollection('test').aggregate([
    {
        $unwind: {
            'path': '$companies'
        }
    },
    {
        $match: {
            'companies.code': {$in: ['0001', '0003']}
        }
    }
    // How do I merge them back into a single document?
]);

Je souhaite filtrer le tableau companies pour supprimer certains objets en fonction du champ code .

J'ai essayé d'utiliser dérouler puis faire correspondre pour filtrer les entreprises, mais je ne sais pas comment recombiner les objets. Y a-t-il une autre façon de faire cela?

Voici ce que j'ai essayé jusqu'à présent:

{
    "_id" : ObjectId("5881cfa62189aa40268b458a"),
    "description" : "Document A",
    "companies" : [ 
        {"code" : "0001"}, 
        {"code" : "0002"}, 
        {"code" : "0003"}
    ]
}


0 commentaires

3 Réponses :


1
votes

Vous pouvez $ group et contrôler la structure du document comme mais c'est un travail fastidieux car vous devez spécifier chaque champ que vous souhaitez conserver.

Je recommande au lieu de vous détendre d'utiliser $ filter pour correspondre aux entreprises comme ceci:

db.getCollection('test').aggregate([
    {
        $addFields: {
            companies: {
                $filter: {
                    input: "$companies",
                    as: "company",
                    cond: {$in: ["$$company.code", ['0001', '0003']]}
                }
            }
        }
    },
    {  // we now need this match as documents with no matched companies might exist
        $match: {
            "companies.0": {$exists: true}
        }
    }
])


4 commentaires

Je ne sais pas si nous avons besoin de l'étape de correspondance $ ici, je suppose qu'OP veut simplement filtrer le tableau des entreprises.


Nous en avons besoin si nous voulons des résultats cohérents comme le fait OP {$ match: {'companies.code': {$ in: ['0001', '0003']}}}


Comme OP a utilisé pour la première fois $ unwind, lorsque $ filter est utilisé, il n'a pas de sens d'utiliser $ match.


Seul $ filter fonctionnait. J'ai initialement essayé d'utiliser match après la décompression pour supprimer les objets de l'entreprise que je ne voulais pas. Merci!



1
votes

Une meilleure façon serait d'utiliser simplement le filtre $ sur le tableau.

db.getCollection('test').aggregate([
    {
     $project: 
       {
         companies: {
             $filter: { 
                  input: '$companies', 
                  as: 'company', 
                  cond: {$in: ['$$company.code', ['0001', '0003']]}
             } 
         }
       }
    }
])


0 commentaires

1
votes

Si vous souhaitez conserver la manière dont vous utilisez le pipeline d'agrégation:

db.getCollection('testcol').aggregate([     
    {$unwind: {'path': '$companies'}},
    {$match: {'companies.code': {$in: ['0001', '0003']}}},     
    {$group: {_id: "$_id", description: { "$first": "$description" } , "companies": { $push: "$companies" }}} ,

])


1 commentaires

Merci! J'ai fini avec $ filter mais votre réponse m'a aidé à apprendre.