skip to Main Content

I need a little help. I’ve a collection which has a field dimension and that field contains array of different objects, which looks like this

Collection – 1:

[
  {
    "_id": {
      "$oid": "6423cddbf4db0d397b22390a"
    },
    "dimension": [
      {
        "_id": {
          "$oid": "6423cde4f4db0d397b22390b"
        },
        "dimensionChild": "Wedding"
      },
      {
        "_id": {
          "$oid": "6423ce0af4db0d397b22390c"
        },
        "dimensionChild": "Business Casual"
      },
      {
        "_id": {
          "$oid": "6423ce18f4db0d397b22390d"
        },
        "dimensionChild": "Formal"
      }
    ]
  },
......
]

and in other object where I’ve available ids from above document (collection – 1) in form of array, which looks likes this,

Collection – 2:

[
  {
    "productTags": [
      {
        "$oid": "6423ce0af4db0d397b22390c" // id from above doc
      },
      {
        "$oid": "6423b723f226c91a55d756bc" // id from different document
      }
    ]
  }
]

Now I need some data like below,

[
  {
    "_id": {
      "$oid": "6423ce0af4db0d397b22390c"
    },
    "dimensionChild": "Business Casual"
  },
  {
    "_id": {
      "$oid": "6423b723f226c91a55d756bc"
    },
    "dimensionChild": "Business Casual 2"
  }
]

Can anyone pls help me to do this. I was using aggregation pipeline to fetch that and my attempt was something like below,

await MODEL.aggregate([
   .....,
    {'$lookup': { "from": 'TEAGET_COLLECTION', "localField": 'productTags', "foreignField": 'dimension._id', as: 'dimensions' } },
   .....,
])

and this actually returning me whole collection 1’s dimension and also those records whose id was not present in Collection – 2’s productTags.

Can anyone please help me to know more about this query.

Thanks,
Soham Roy

2

Answers


    1. Collection 1 joins with collection 2. The output for this stage will be the document with a dimensions array.

    2. As $lookup stage in MongoDB is LEFT JOIN. To perform join, you have to filter the document with dimensions is not an empty array.

    3. Set the productTags field by concatenating nested array from dimensions.productTags into an array via $reduce.

    4. Filter the dimension array with the document that its _id is existed in the productTags array.

    5. $unwind – Deconstruct the dimension array into multiple documents.

    6. $replaceWith – Replace the input document with dimension object.

    db.col1.aggregate([
      {
        "$lookup": {
          "from": "col2",
          "localField": "dimension._id",
          "foreignField": "productTags",
          as: "dimensions"
        }
      },
      {
        $match: {
          dimensions: {
            $ne: []
          }
        }
      },
      {
        $set: {
          productTags: {
            $reduce: {
              input: "$dimensions",
              initialValue: [],
              in: {
                $concatArrays: [
                  "$$value",
                  "$$this.productTags"
                ]
              }
            }
          }
        }
      },
      {
        $set: {
          dimension: {
            $filter: {
              input: "$dimension",
              cond: {
                $in: [
                  "$$this._id",
                  "$productTags"
                ]
              }
            }
          }
        }
      },
      {
        $unwind: "$dimension"
      },
      {
        $replaceWith: "$dimension"
      }
    ])
    

    Demo @ Mongo Playground

    Login or Signup to reply.
  1. Another option is:

    db.collection1.aggregate([
      {$lookup: {
          from: "collection2",
          localField: "productTags",
          foreignField: "dimension._id",
          as: "collection2"
      }},
      {$project: {
          dimension: {$filter: {
              input: "$dimension",
              cond: {$in: [
                  "$$this._id",
                  {$getField: {input: {$first: "$collection2"}, field: "productTags"}}
              ]}
          }}
      }},
      {$unwind: "$dimension"},
      {$replaceRoot: {newRoot: "$dimension"}}
    ])
    

    See how it works on the playground example

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search