How to conditionally remove a field from an array of objects in MongoDB?

Viewed 218

I have a Listing collection with the following document:

{
  owner: ObjectId('12345678'),
  bids: [
    {
      amount: 36,
      date: 2021-06-23T21:00:00.000+00:00,
      placedBy: ObjectId('1111111')
    },
    {
      amount: 16,
      date: 2021-06-23T21:00:00.000+00:00,
      placedBy: ObjectId('22223332')
    }
  ]
}

I need to query the bids array, but remove the field placedBy (for all elements in the array) only if a condition is met. This is what I have so far:

async getBids(listingId: string, user: UserDocument) {
        return this.listingModel.aggregate([
            { $match: { _id: Types.ObjectId(listingId) } },
            {
                $project: {
                    'bids.date': 1,
                    'bids.amount': 1,
                    'bids.placedBy': {
                        $cond: {
                            if: {
                                '$eq': ['$owner', Types.ObjectId(user.id)]
                            },
                            then: '$bids.placedBy',
                            else: '$$REMOVE'
                        }
                    }
                }
            }
        ])
    }

This works fine for when the condition is false (bids.placedBy is removed), but when the condition is met I get this (bids.placedBy turns into an array of all placedBys):

bids: [
    {
      amount: 36,
      date: 2021-06-23T21:00:00.000+00:00,
      placedBy: [
        ObjectId('1111111'),
        ObjectId('22223332')
      ]
    },
    {
      amount: 16,
      date: 2021-06-23T21:00:00.000+00:00,
      placedBy: [
        ObjectId('1111111'),
        ObjectId('22223332')
      ]
    }
  ]

How can I fix this?

1 Answers

You can use $map to loop over the array and set the condition

db.collection.aggregate([
  {
    $project: {
      "bids": {
        "$map": {
          "input": "$bids",
          "in": {
            amount: "$$this.amount",
            date: "$$this.date",
            placedBy: {
              $cond: [ { "$eq": [ "$owner", 1 ] }, "$$this.placedBy", "$$REMOVE" ]
            }
          }
        }
      }
    }
  }
])

Working Mongo playground

Related