Double array $lookup call preserving original structure

Advertisements

I’m trying to populate a double array object but in an aggregate so I am utilizing the $lookup function. The collection looks something like this:

{
  foo: [
    {
      bar: [
        {
          _id: ObjectId('63f508eedd2962118c37ea36')
        }
      ]
    }
  ]
}

My lookup looks like:

{
  $lookup: {
    from: "collection",
    localField: "foo.bar",
    foreignField: "_id",
    as: "foo.bar",
  },
}

which results in

{
  foo: {
    bar: [
      {
        _id: ObjectId('63f508eedd2962118c37ea36'),
        field1: "helloworld"
      }
    ]
  }
}

where what I actually want is

{
  foo: [
    {
      bar: [
        {
          _id: ObjectId('63f508eedd2962118c37ea36'),
          field1: "helloworld"
        }
      ]
    }
  ]
}

Any ideas on how to achieve what I want in an aggregate?

>Solution :

Seems a direct map with $lookup for the nested array is not possible.

  1. $lookup – Join the collection collection and return the bars array field.

  2. $set – Set foo array.

    2.1. $map – Iterate element in foo array.

    2.1.1. $mergeObjects – Merge current iterated foo element with the result of 2.1.1.1.

    2.1.1.1. A document with a bar field which contains the result of 2.1.1.1.1.

    2.1.1.1.1. $map – Iterate element in bar array.

    2.1.1.1.1.1. $mergeObjects – Merge the current iterated bar element with the result of 2.1.1.1.1.1.1.

    2.1.1.1.1.1.1. $first – Get the first matching element from the bars array by _ids.

  3. $unset – Remove bars array.

db.from.aggregate([
  {
    $lookup: {
      from: "collection",
      localField: "foo.bar._id",
      foreignField: "_id",
      as: "bars"
    }
  },
  {
    $set: {
      foo: {
        $map: {
          input: "$foo",
          as: "foo",
          in: {
            $mergeObjects: [
              "$$foo",
              {
                bar: {
                  $map: {
                    input: "$$foo.bar",
                    as: "bar",
                    in: {
                      $mergeObjects: [
                        "$$bar",
                        {
                          $first: {
                            $filter: {
                              input: "$bars",
                              cond: {
                                $eq: [
                                  "$$bar._id",
                                  "$$this._id"
                                ]
                              }
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      }
    }
  },
  {
    $unset: "bars"
  }
])

Demo @ Mongo Playground

Leave a ReplyCancel reply