0
{
    "source": "Chennai",
    "destination": "Kolkata",
    "flights": [
        {
            "flightId": "E6-2145",
            "seatsAvailable": 10,
            "fare": [
                {
                    "travelClass": "Economy",
                    "baseFare": 3588
                },
                {
                    "travelClass": "Business",
                    "baseFare": 9999
                }
            ]
        }
    ]
}

I want to update the basefare of Economy class to 3800 if it is less than 3800.

I tried:

db.Flights.aggregate({
  $unwind: "$flights"
},
{
  $match: {
    "flights.fare": {
      $elemMatch: {
        travelClass: "Economy",
        baseFare: {
          $lt: 3800
        }
      }
    }
  }
},
{
  $set: {
    "flights.fare.basefare": 3800
  }
})

But it is updating both basefares of the flight i.e Economy as well as Business to 3800.

Please help me to solve this.

1 Answer 1

1

It is due to flight.fare is an array, by setting the value with flight.fare.baseFare, it will update the basefare value of each document in flight.fare array.

You need $map operator to iterate each document in flight.fare array and update the basefare value if the document fulfilled the condition.

Solution 1

db.collection.aggregate([
  {
    $unwind: "$flights"
  },
  {
    $match: {
      "flights.fare": {
        $elemMatch: {
          travelClass: "Economy",
          baseFare: {
            $lt: 3800
          }
        }
      }
    }
  },
  {
    $set: {
      "flights.fare": {
        $map: {
          input: "$flights.fare",
          as: "fare",
          in: {
            $cond: {
              if: {
                $and: [
                  {
                    $eq: [
                      "$$fare.travelClass",
                      "Economy"
                    ]
                  },
                  {
                    $lt: [
                      "$$fare.baseFare",
                      3800
                    ]
                  }
                ]
              },
              then: {
                $mergeObjects: [
                  "$$fare",
                  {
                    baseFare: 3800
                  }
                ]
              },
              else: "$$fare"
            }
          }
        }
      }
    }
  }
])

Demo Solution 1 @ Mongo Playground


Solution 2: Without $unwind

db.collection.aggregate([
  {
    $set: {
      flights: {
        $map: {
          input: "$flights",
          as: "flight",
          in: {
            $mergeObjects: [
              "$$flight",
              {
                fare: {
                  $map: {
                    input: "$$flight.fare",
                    in: {
                      $cond: {
                        if: {
                          $and: [
                            {
                              $eq: [
                                "$$this.travelClass",
                                "Economy"
                              ]
                            },
                            {
                              $lt: [
                                "$$this.baseFare",
                                3800
                              ]
                            }
                          ]
                        },
                        then: {
                          $mergeObjects: [
                            "$$this",
                            {
                              baseFare: 3800
                            }
                          ]
                        },
                        else: "$$this"
                      }
                    }
                  }
                }
              }
            ]
          }
        }
      }
    }
  }
])

Demo Solution 2 @ Mongo Playground

Note: Both aggregation queries will result in the value being updated for the projection, but won't update the document in the collection.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.