mongodbaggregation-frameworklookup

Array is reordered when using $lookup


I have this aggregation:

db.getCollection("users").aggregate([
  {
    "$match": {
      "_id": "5a708a38e6a4078bd49f01d5"
    }
  },
  {
    "$lookup": {
      "from": "user-locations",
      "localField": "locations",
      "as": "locations",
      "foreignField": "_id"
    }
  }
])

It works well, but there is one small thing that I don't understand and I can't fix. In the query output, the locations array is reordered by ObjectId and I really need to keep the original order of data.

Here is how the locations array from the users collection looks like

'locations' : [
     ObjectId("5b55e9820b720a1a7cd19633"), 
     ObjectId("5a708a38e6a4078bd49ef13f")
], 

And here is the result after the aggregation:

'locations' : [
     {
        '_id' : ObjectId("5a708a38e6a4078bd49ef13f"),
        'name': 'Location 2'
     },
     {
        '_id' : ObjectId("5b55e9820b720a1a7cd19633"),
        'name': 'Location 1'
     }
],

What am I missing here? I really have no idea how to proceed with this issue. Could you give me a push?


Solution

  • $lookup does not guarantee order of result documents, you can try a approach to manage natural order of document,

    db.users.aggregate([
      { $match: { _id: "5a708a38e6a4078bd49f01d5" } },
      {
        $unwind: {
          path: "$locations",
          includeArrayIndex: "index"
        }
      },
      {
        $lookup: {
          from: "user-locations",
          localField: "locations",
          foreignField: "_id",
          as: "locations"
        }
      },
      { $set: { locations: { $arrayElemAt: ["$locations", 0] } } },
      { $sort: { index: 1 } },
      {
        $group: {
          _id: "$_id",
          locations: { $push: "$locations" }
        }
      }
    ])
    

    Playground