MongoDB aggregation to replace array of ObjectIds with actual documents

Let's say we have this db.orders document collection with one document:

{"_id": "5ef62e0c586c78491530e4d5", "items": [{ "description": "desc1", "parts": ["5ef62e0c586c78491530e4d7", "5ef62e0c586c78491530e4d8"] } ], "createdBy": "userId"}

[CORRECTION: the items field is now an array]

And another db.parts collection with two part documents:

{"_id": "5ef62e0c586c78491530e4d7", "name": "part1" }
{"_id": "5ef62e0c586c78491530e4d8", "name": "part2" }

I would like to construct an aggregation on the first collection replacing the ObjectIds in the parts array with the actual documents. The result should be like:

{"_id": "5ef62e0c586c78491530e4d5", "items": [{ "description": "desc1", "parts":
  [
    {"_id": "5ef62e0c586c78491530e4d7", "name": "part1" },
    {"_id": "5ef62e0c586c78491530e4d8", "name": "part2" }
  ]
}], "createdBy": "userId"}

Any ideas would be much appreciated!

Upvotes: 3

Views: 568

Answers (1)

Valijon
Valijon

Reputation: 13103

You need to use the $lookup operator:

db.orders.aggregate([
  {
    $lookup: {
      from: "parts",
      localField: "items.parts",
      foreignField: "_id",
      as: "parts"
    }
  },
  {
    $project: {
      createdBy: 1,
      items: {
        $map: {
          input: "$items",
          as: "item",
          in: {
            description: "$$item.description",
            parts: {
              $filter: {
                input: "$parts",
                as: "part",
                cond: {
                  $in: [ "$$part._id", "$$item.parts" ]
                }
              }
            }
          }
        }
      }
    }
  }
])

MongoPlayground

Upvotes: 1

Related Questions