Search code examples
mongodbmongoosemongodb-query

mongodb $lookup - but return from second collection only a part of the sub collection


I have two collections:

  • posts
  • images

The images should be returned based on the post id(s) but only a part of the image sub collection should be returned. The result should only return the current entry of the sub collection that has the same lang.

That's what I have so far:

Post document
{
  "_id": 1,
  "lang": "en",
  "content": "foobar"
}
Image document
{
  "_id": ...,
  "post_id": 1,
  "title": [
    {
      "lang": "de",
      "value": "hallo welt"
    },
    {
      "lang": "en",
      "value": "hello world"
    }
  ],
}
Current code
Post.aggregate([
  { $match: query },
  {
    $lookup: {
      from: 'images',
      localField: '_id',
      foreignField: 'post_id',
      as: 'images',
    },
  },
  {
    $project: {
      content: 1,
      lang: 1,
      images: 1,
    },
  }
]);

But this will return the whole sub collection (en/de) but I just need the matched language. How can I solve this?

Thanks!


Solution

  • One way to limit what is returned from each document in"$lookup"'s "from" collection, is to use a "pipeline" in the "$lookup". Additionally, "$lookup"'s "let" optional field can be used to pass current document field values to the "pipeline".

    db.posts.aggregate([
      {
        "$match": {
          // whatever filter is required goes here
          "_id": 1
        }
      },
      {
        "$lookup": {
          "from": "images",
          "localField": "_id",
          "foreignField": "post_id",
          "as": "images",
          // assign lang so it can be used in pipeline
          "let": {
            "lang": "$lang"
          },
          "pipeline": [
            {
              "$set": {
                "title": {
                  // only return elements matching lang
                  "$filter": {
                    "input": "$title",
                    "cond": {
                      "$eq": ["$$this.lang", "$$lang"]
                    }
                  }
                }
              }
            }
          ]
        }
      }
    ])
    

    Try it on mongoplayground.net.