Home > Mobile >  How to filter an array of objects to remove elements based on condition in MongoDB aggregate?
How to filter an array of objects to remove elements based on condition in MongoDB aggregate?

Time:04-28

I have a collection of documents ChatRooms in MongoDB that has this (simplified) structure:

{
  _id: ObjectId('4654'),
  messages: [
    {
      user: ObjectId('1234'),
      sentAt: ISODate('2022-03-01T00:00:00.000Z')
    },
    {
      user: ObjectId('1234'),
      sentAt: ISODate('2022-03-02T00:00:00.000Z')
    },
    {
      user: ObjectId('8888'),
      sentAt: ISODate('2022-03-03T00:00:00.000Z')
    },
  ]
}

What I'm trying to achieve is to filter the messages array inside the aggregate pipeline in order to get an array where the userId is presend just once. The result I'm looking for is (or something similar but the array shouldn't have two elements with the same user id):

{
  _id: ObjectId('4654'),
  messages: [
    {
      user: ObjectId('1234'),
      sentAt: ISODate('2022-03-01T00:00:00.000Z')
    },
    {
      user: ObjectId('8888'),
      sentAt: ISODate('2022-03-03T00:00:00.000Z')
    },
  ]
}

Is such a thing possible even? Any help would be much appreciated.

CodePudding user response:

You can do this in several different ways, here is an example of how to achieve this using the $reduce operator:

db.collection.aggregate([
  {
    $addFields: {
      messages: {
        $reduce: {
          input: "$messages",
          initialValue: [],
          in: {
            $cond: [
              {
                $in: [
                  "$$this.user",
                  "$$value.user"
                ]
              },
              "$$value",
              {
                "$concatArrays": [
                  "$$value",
                  [
                    "$$this"
                  ]
                ]
              }
            ]
          }
        }
      }
    }
  }
])

Mongo Playground

  • Related