具有嵌套查询的Mongodb聚合复杂文档

时间:2020-08-18 15:31:48

标签: mongodb

我有这些收藏夹:

站点

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

模板

{
  _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...)
     ]
}

字段

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

我是MongoDB的新手,但花了几天时间阅读了问题和解答以及文档。我正在使用MongoDB 4.2.6。我正在尝试返回这样的格式的结果:

{
  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"
           }
        }, (...)]
      }]
}
  

我编写了一个带有嵌套查询的汇总查询,以使我大部分时间都在那儿,但是要使其正常工作,我必须先展开 Sections FieldItems 。我还没有找到一种使数组达到我想要的方式的方法。我试过组,但与子数组有问题。我什至不确定这是否是获得所需结果的最佳方法:

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

1 个答案:

答案 0 :(得分:1)

您完成了两次$unwind,因此您需要使用两次$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. 第一个组-对子对象进行分组。但是类型,名称和标题需要分别设置为父数组和子数组。
  2. 第二组-对父对象进行分组。我们在对孩子进行分组时获得了每个独立的字段。在这里,我们只需要在正确的订单上进行设置即可。

工作Mongo playground

注意:当您使用$lookup时,它将提供一个数组。但是在某些地方您只是将其作为对象。我不知道您是否加入一对一的关系。如果是这样,您可以使用positional operator in projectionarrayElemAt