5

I have a collection that looks like the following and i'm having troubles to perform a $lookup and return it the way it was at the beginning but with the populated fields:

i have made comments on the fields i want to populate which are (agent, missions.clients.client)

 {  
   "title":"Tournée libre",
   "agent":"5d811943d2a2100017667228", // needs to be populated
   "missions":[  
      {  
         "_id":"5d8a075346f10d679ab4383e",
         "title":"Journée 3",
         "clients":[  
            {  
               "_id":"5d8a075346f10d679ab4383f",
               "valid":true,
               "client":"5d1bc39aa2af623b94363b33", // this needs to be populated
               "visit_time":"2019-09-24T12:03:38.383Z"
            },
            {  

               "_id":"5d8a0dc446f10d679ab43888",
               "valid":true,
               "client":"5d8a0c8346f10d679ab43886",
               "visit_time":"2019-09-24T12:34:23.210Z"
            },

         ]
      }
   ],
   "created_at":"2019-09-24T12:08:51.928Z",
   "__v":2
}

and here is how the result should be:

 {  
   "title":"Tournée libre",
   "agent": {firstname: 'something', lastname: 'something else'}
   "missions":[  
      {  
         "_id":"5d8a075346f10d679ab4383e",
         "title":"Journée 3",
         "clients":[  
            {  
               "_id":"5d8a075346f10d679ab4383f",
               "valid":true,
               "client": {firstname: 'something', lastname: 'something else'},
               "visit_time":"2019-09-24T12:03:38.383Z"
            },
            {  

               "_id":"5d8a0dc446f10d679ab43888",
               "valid":true,
               "client":{firstname: 'something', lastname: 'something else'},
               "visit_time":"2019-09-24T12:34:23.210Z"
            },

         ]
      }
   ],
   "created_at":"2019-09-24T12:08:51.928Z",
   "__v":2
}
2
  • .populate(agent missions.clients.client') Give it a try Commented Sep 24, 2019 at 17:35
  • I was using populate but I ran into a performance problem considering that I'm implementing pagination and I have user roles. So aggregate is what I'm asking for Commented Sep 24, 2019 at 23:12

1 Answer 1

9
+50

You could use below aggregation pipeline.

$lookup to populate agent followed by $reduce and $concatArrays to collect all the client ids and $lookup to get the client details.

$addFields with $map to iterate mission array and for each client map the client info from previous stage by lookup by client id and $mergeObjects to keep the other fields. $project stage to remove the extra fields.

Mongo db 3.6 and above

Model.aggregate([
 {"$lookup":{
  "from":"agents",
  "localField":"agent",
  "foreignField":"_id",
  "as":"agent"
 }},
 {"$addFields":{"agent":{"$arrayElemAt":["$agent",0]}}},
 {"$addFields":{
   "client_ids":{
     "$reduce":{
       "input":"$missions",
       "initialValue":[],
       "in": {"$concatArrays":["$$value","$$this.clients.client"]}
     }
   }
 }},
 {"$lookup":{
   "from":"clients",
   "localField":"client_ids",
   "foreignField":"_id",
   "as":"client_info"
 }},
 {"$addFields":{
   "missions":{
     "$map":{
       "input":"$missions",
       "in":{
         "$mergeObjects":[
           "$$this",
           {"clients":{"$map":{
             "input":"$$this.clients",
             "in":{"$mergeObjects":[
               "$$this",
              {"client":{"$arrayElemAt":[
                "$client_info",
                {"$indexOfArray":["$client_ids","$$this._id"]}
              ]}}
            ]}
           }}}
         ]
       }
     }
   }
 }},
 {"$project":{"client_ids":0,"client_info":0}}
])

Mongo db less than 3.6

$lookup to populate agent followed by $unwind to reach client and look up to get the client details. Rewind with $group to bring back to original structure with populated values.

Model.aggregate([
 {"$lookup":{
  "from":"agents",
  "localField":"agent",
  "foreignField":"_id",
  "as":"agent"
 }},
 {"$addFields":{"agent":{"$arrayElemAt":["$agent",0]}}},
 {"$unwind":"$missions"},
 {"$unwind":"$missions.clients"},
 {"$lookup":{
   "from":"clients",
   "localField":"missions.clients.client",
   "foreignField":"_id",
   "as":"missions.clients.client"
 }},
 {"$addFields":{"missions.clients.client":{"$arrayElemAt":["$missions.clients.client",0]}}},
 {"$group":{
   "_id":{"_id":"$_id","mission_id":"$missions._id"},
   "agent":{"$first":"$agent"},
   "title":{"$first":"$missions.title"},
   "clients":{"$push":"$missions.clients"}
 }},
 {"$group":{
   "_id":"$_id._id",
   "agent":{"$first":"$agent"},
   "missions":{
     "$push":{
       "_id":"$_id.mission_id",
       "title":"$title",
       "clients":"$clients"
      }
    }
 }}
])
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.