Search code examples
mongodbaggregation-frameworkquery-optimizationaggregation

MongoDB Aggregation - Conditional $lookup depending if a field exists or not


I have two collections called collection1, and collection2 and they are structured as follows,

// collection1

[
  { "_id": 100, "text": "i am good", "history":[{"date":"2023-6-1", "updated":"2023-6-2"}] },
  { "_id": 101, "text": "i am naughty"}
]

// collection2

[
  { "_id": 1,collection1Id:100, "date":"2023-6-1", "updated":"2023-6-2" },  // is present in 1 so should not goto this collection
  { "_id": 2,collection1Id:101, "date":"2023-7-3", "updated":"2023-7-5" }
]

I want the aggregation query to run such that if the field (history) does not exist inside collection1 then lookup to collection2 should be made. See the code below:

db.collection1.aggreagte([

if history is not exist in collection1
{
lookup from collection2
}

])

Expected Output

After the aggregation executes, I want the result to be shown below:

[
  { "_id": 100, "text": "i am good", "history":[{"date":"2023-6-1", "updated":"2023-6-2"}] },
  { "_id": 2,"text": "i am naughty", "history":[{"_id": 2, collection1Id: 101, "date":"2023-7-3", "updated":"2023-7-5"}],  } // history has been taken from collection 2 
]

The first row is from collection1 only because history exists and the second record is from collection2 where I did lookup as the history field did not exist in the primary collection.


Solution

  • I don't think that is possible to conditional $lookup join another collection.

    But, you can achieve create the history field if the history field is missing then assign it with the collection2 value. Otherwise, remain its existing value.

    db.collection1.aggregate([
      {
        "$lookup": {
          "from": "collection2",
          "localField": "_id",
          "foreignField": "collection1Id",
          "as": "collection2"
        }
      },
      {
        $set: {
          history: {
            "$cond": {
              "if": {
                $eq: [
                  {
                    $type: "$history"
                  },
                  "missing"
                ]
              },
              "then": "$collection2",
              "else": "$history"
            }
          }
        }
      },
      {
        $unset: "collection2"
      }
    ])
    

    Demo @ Mongo Playground