Document complexe agrégé Mongodb avec des recherches imbriquées

Aug 19 2020

J'ai ces collections:

Des sites

{
  _id: ObjectId("5acdb8f65ea63a27c1facf86"),
  TemplateId: ObjectId("sdfsdfs34234234sdf"),
}

Modèles

{
  _id: ObjectId("sdfsdfs34234234sdf"),
  Type: "Site",
  Name: "Site 1",
  Sections:[{
     id: ObjectId("8asdf89asd8f9sdf"),
     Header: "Header1",
     FieldItems: [
           {
            FieldId: ObjectId("jsd32423423423"),
            x: 1,
            y: 0
           },
           {
            FieldId: ObjectId("2342sdffafdasdfdfs"),
            x: 1,
            y: 1
           }
          ]
        },
       (...more sections...)
     ]
}

Des champs

{
  _id: ObjectId("jsd32423423423"),
  Type: "Phone",
  Name: "Phone_Test"
},
{
  _id: ObjectId("2342sdffafdasdfdfs"),
  Type: "Numeric",
  Name: "Number_Test"
}
            

Je suis nouveau sur MongoDB, mais j'ai mis quelques jours à lire les questions et réponses ainsi que la documentation. J'utilise MongoDB 4.2.6. J'essaye de renvoyer un résultat formaté comme ceci:

{
  id: ObjectId("5acdb8f65ea63a27c1facf86"),
  TemplateId: ObjectId("sdfsdfs34234234sdf"),
  Template: {
   id: ObjectId("sdfsdfs34234234sdf"),
   Type: "Site",
   Sections:[{
     id: ObjectId("8asdf89asd8f9sdf"),
     Header: "Header1",
     FieldItems: [
        {
          FieldId: ObjectId("jsd32423423423"),
          x: 1,
          y: 0,
          Field: {
              _id: ObjectId("jsd32423423423"),
              Type: "Phone",
              Name: "Phone_Test"
           }
        }, (...)]
      }]
}
  

J'ai écrit une requête agrégée avec des recherches imbriquées pour m'y amener principalement, mais pour que cela fonctionne, j'ai dû dérouler Sections et FieldItems . Je n'ai pas trouvé un moyen pour obtenir les tableaux comme je les aimerais. J'ai essayé le groupe mais j'ai des problèmes avec les sous-tableaux. Je ne sais même pas si c'est la meilleure façon d'obtenir les résultats dont j'ai besoin:

db.getCollection("AppSites").aggregate(
[
    { 
        "$lookup" : { "from" : "AppTemplates", "let": {"template_id": "$TemplateId"},
            "pipeline": [
                { "$match": { "$expr": { "$eq" : ["$_id", "$$template_id"] } } }, { "$unwind": "$Sections"}, { "$unwind": "$Sections.FieldItems"}, { "$lookup": {
                        "from": "AppFields",
                        "let": {"field_id": "$Sections.FieldItems.FieldId"}, "pipeline": [ { "$match": { "$expr": { "$eq": ["$_id", "$$field_id"] } } }
                        ],
                        "as": "Sections.FieldItems.Field"
                    }
                }
            ],
            "as" : "Templates"
        }
    }
]
);

Réponses

1 varman Aug 19 2020 at 00:21

Vous avez fait $unwinddeux fois, vous devez donc en utiliser deux $group.

{
  $group: { _id: { secId: "$_id",
      fId: "$Sections.id" }, Type: { $first: "$Type" }, Name: { $first: "$Name" }, Header: { $first: "$Sections.Header" }, fieldItems: { $push: "$Sections.FieldItems" } } }, { $group: {
    _id: "$_id.secId", Type: { $first: "$Type" }, Name: { $first: "$Name" }, Sections: { $push: {
        id: "$_id.fId", Header: "$Header",
        fieldItems: "$fieldItems"
      }
    }
  }
}
  1. Premier groupe - pour regrouper les objets enfants. Mais le type, le nom et l'en-tête doivent être définis respectivement sur les tableaux parent et enfant.
  2. Deuxième groupe - pour regrouper les objets parents. Nous obtenons tous les champs autonomes lors du regroupement des enfants. Ici, nous avons juste besoin de le configurer dans des oreders corrects.

Travail aire de jeux Mongo

Remarque: lorsque vous utilisez $lookup, il fournira un tableau. Mais il y a des endroits où vous en faites un objet. Je ne sais pas si vous vous joignez à une relation individuelle ou non. Si c'est le cas, vous pouvez utiliser l' opérateur de position dans la projection ou arrayElemAt