简体   繁体   中英

Mongodb Aggregation with separate collections

I had a problem with mongodb aggregation with more than 2 collections. Here i represent my collections.
First Collection: potential

{
 "_id" : ObjectId("5a0d1cb1d2fffa95ed85b3ba"),
 "potential_id" : "P-00012347",
 "potential_name" : "NKCL"}

My second collection: office

{
"_id" : ObjectId("5a0d20e8d2fffa95ed85b5bc"),
"potential_id" : "P-00012347",
"potential_name" : "NKCL",
"revision_id" : "R0",
"office_name" : "Marketing office",
"vertical_info" : [ 
    {
        "vertical_name" : "MEP",
        "estimated_team" : "Marketing"
    }, 
    {
        "vertical_name" : "BIM",
        "estimated_team" : "Marketing"
    }, 
    {
        "vertical_name" : "V1",
        "estimated_team" : "Marketing"
    }
]}

My third collection: services

{
"_id" : ObjectId("5a0d212cd2fffa95ed85b5e6"),
"potential_id" : "P-00012347",
"potential_name" : "NKCL",
"revision_id" : "R0",
"office_name" : "Marketing office",
"vertical_name" : "MEP",
"service_info" : [ 
    {
        "service_name" : "Service 1",
        "total_cost" : 1
    }, 
    {
        "service_name" : "Service 2",
        "total_cost" : 2
    }
]}

My fourth collection: servicebuild

  {
"_id" : ObjectId("5a0d2175d2fffa95ed85b612"),
"potential_id" : "P-00012347",
"potential_name" : "NKCL",
"revision_id" : "R0",
"office_name" : "Marketing office",
"vertical_name" : "MEP",
"service_name" : "Service 1",
"service_building_info" : [ 
    {
        "building_no" : 1,
        "building_name" : "Building 1"
    }, 
    {
        "building_no" : 2,
        "building_name" : "Building 2"
    }, 
    {
        "building_no" : 3,
        "building_name" : "Building 3"
    }
]}

Now i want to join the above 4 collections with in a single aggregation query. I saw the most of the examples to join only the two collections.

My output look like this

{
  "_id" : ObjectId("5a0d1cb1d2fffa95ed85b3ba"),
 "potential_id" : "P-00012347",
 "potential_name" : "NKCL"
 "revision_id" : "R0",
"office_name" : "Marketing office",
 "vertical_info" : [ 
{
    "vertical_name" : "MEP",
    "estimated_team" : "Marketing"
    "service_info" : [ 
        {
            "service_name" : "Service 1",
            "total_cost" : 1
            "service_building_info" : [ 
                {
                    "building_no" : 1,
                    "building_name" : "Building 1"
                }, 
                {
                    "building_no" : 2,
                    "building_name" : "Building 2"
                }, 
                {
                    "building_no" : 3,
                    "building_name" : "Building 3"
                }
            ]
        }, 
        {
            "service_name" : "Service 2",
            "total_cost" : 2
        }
    ]
}, 
{
    "vertical_name" : "BIM",
    "estimated_team" : "Marketing"
}, 
{
    "vertical_name" : "V1",
    "estimated_team" : "Marketing"
}]}

Anyone can help to solve my problem.

Here is the aggregation which results your desired output:

db.potential.aggregate([{
    $lookup: {
      from: 'office',
      localField: 'potential-id',
      foreignField: 'potential-id',
      as: 'office'
    }
  },
  {
    $unwind: '$office'
  },
  {
    $project: {
      potential_id: 1,
      potential_name: 1,
      revision_id: '$office.revision_id',
      office_name: '$office.office_name',
      vertical_info: '$office.vertical_info'
    }
  },
  {
    $lookup: {
      from: 'services',
      localField: 'vertical_info.vertical_name',
      foreignField: 'vertical_name',
      as: 'services'
    }
  },
  {
    $project: {
      potential_id: 1,
      potential_name: 1,
      revision_id: 1,
      office_name: 1,
      vertical_info: {
        $map: {
          input: '$vertical_info',
          as: 'vertical_info_item',
          in: {
            vertical_name: '$$vertical_info_item.vertical_name',
            estimated_team: '$$vertical_info_item.estimated_team',
            service_info: {
              $filter: {
                input: '$services',
                as: 'service',
                cond: {
                  $eq: ['$$vertical_info_item.vertical_name', '$$service.vertical_name']
                }
              }
            }
          }
        }
      }
    }
  },
  {
    $project: {
      potential_id: 1,
      potential_name: 1,
      revision_id: 1,
      office_name: 1,
      vertical_info: {
        $map: {
          input: '$vertical_info',
          as: 'vertical_info_item',
          in: {
            vertical_name: '$$vertical_info_item.vertical_name',
            estimated_team: '$$vertical_info_item.estimated_team',
            service_info: {
              $arrayElemAt: ['$$vertical_info_item.service_info.service_info', 0]
            }
          }
        }
      }
    }
  },
  {
    $lookup: {
      from: 'servicebuild',
      localField: 'vertical_info.service_info.service_name',
      foreignField: 'service_name',
      as: 'servicebuild'
    }
  },
  {
    $project: {
      potential_id: 1,
      potential_name: 1,
      revision_id: 1,
      office_name: 1,
      vertical_info: {
        $map: {
          input: '$vertical_info',
          as: 'vertical_info_item',
          in: {
            vertical_name: '$$vertical_info_item.vertical_name',
            estimated_team: '$$vertical_info_item.estimated_team',
            service_info: {
              $map: {
                input: '$$vertical_info_item.service_info',
                as: 'service_info_item',
                in: {
                  service_name: '$$service_info_item.service_name',
                  total_cost: '$$service_info_item.total_cost',
                  service_building_info: {
                    $filter: {
                      input: '$servicebuild',
                      as: 'servicebuild_item',
                      cond: {
                        $eq: ['$$service_info_item.service_name', '$$servicebuild_item.service_name']
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  {
    $project: {
      potential_id: 1,
      potential_name: 1,
      revision_id: 1,
      office_name: 1,
      vertical_info: {
        $map: {
          input: '$vertical_info',
          as: 'vertical_info_item',
          in: {
            $cond: {
              if: {
                $ne: ['$$vertical_info_item.service_info', null]
              },
              then: {
                vertical_name: '$$vertical_info_item.vertical_name',
                estimated_team: '$$vertical_info_item.estimated_team',
                service_info: {
                  $map: {
                    input: '$$vertical_info_item.service_info',
                    as: 'service_info_item',
                    in: {
                      service_name: '$$service_info_item.service_name',
                      total_cost: '$$service_info_item.total_cost',
                      service_building_info: {
                        $filter: {
                          input: '$$service_info_item.service_building_info',
                          as: 'servicebuild_item',
                          cond: {
                            $eq: ['$$service_info_item.service_name', '$$servicebuild_item.service_name']
                          }
                        }
                      }
                    }
                  }
                }
              },
              else: {
                vertical_name: '$$vertical_info_item.vertical_name',
                estimated_team: '$$vertical_info_item.estimated_team'
              }
            }
          }
        }
      }
    }
  },
  {
    $project: {
      potential_id: 1,
      potential_name: 1,
      revision_id: 1,
      office_name: 1,
      vertical_info: {
        $map: {
          input: '$vertical_info',
          as: 'vertical_info_item',
          in: {
            $cond: {
              if: {
                $ne: ['$$vertical_info_item.service_info', undefined]
              },
              then: {
                vertical_name: '$$vertical_info_item.vertical_name',
                estimated_team: '$$vertical_info_item.estimated_team',
                service_info: {
                  $map: {
                    input: '$$vertical_info_item.service_info',
                    as: 'service_info_item',
                    in: {
                      service_name: '$$service_info_item.service_name',
                      total_cost: '$$service_info_item.total_cost',
                      service_building_info: {
                        $arrayElemAt: ['$$service_info_item.service_building_info.service_building_info', 0]
                      }
                    }
                  }
                }
              },
              else: {
                vertical_name: '$$vertical_info_item.vertical_name',
                estimated_team: '$$vertical_info_item.estimated_team'
              }
            }
          }
        }
      }
    }
  }
])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM