Search code examples
mongodbmongoose

Mongoose query to get an inner array and a specific element from that inner array


I am trying to retriev an array from a mongoose schema usging the aggragate function fron mongoose. I am using nestjs for this project, but the queries are the same:

const notifications = await this.userRepo.aggregate( [
      { $match: { _id: userId } },
      { $unwind: "$notifications" },
      { $replaceRoot: { newRoot: '$notifications' } }
] );

The problem here is that every time I am getting an empty array. No matter what is inside the document.

Here is a document example:

{
  _id: new ObjectId("6471fe4a0045e48a0c6193ba"),
  gateways: [
    {
      _id: '5231db1f-b79a-4dc3-a387-6f08ad7b6857',
      name: 'Babylon Dev',
      right: 'owner'
    }
  ],
  __v: 0,
  notifications: [
    {
      type: 'confirm',
      title: 'Gateway whitelist request!',
      description: '6471fe4a0045e48a0c6193ba wants to share data from gateway 5231db1f-b79a-4dc3-a387-6f08ad7b6857 with you.',
      actions: [Array],
      from: '6471fe4a0045e48a0c6193ba',
      subject: '5231db1f-b79a-4dc3-a387-6f08ad7b6857',
      status: 'unread',
      _id: new ObjectId("64b6791adbf7bb6eaa528cf2")
    }
  ]
}

Can someone clue me in where am I setting this up wrong?

The result that I want is to get the notifications array:

[
    {
      type: 'confirm',
      title: 'Gateway whitelist request!',
      description: '6471fe4a0045e48a0c6193ba wants to share data from gateway 5231db1f-b79a-4dc3-a387-6f08ad7b6857 with you.',
      actions: [Array],
      from: '6471fe4a0045e48a0c6193ba',
      subject: '5231db1f-b79a-4dc3-a387-6f08ad7b6857',
      status: 'unread',
      _id: new ObjectId("64b6791adbf7bb6eaa528cf2")
    }
  ]

Also it would help to get/update/delete one element inside the notifications array.


Solution

  • make sure the userId is the same type as what is stored in the database. In your case it is an ObjectId. you can find here how to do it.
    playground

    const notifications = await this.userRepo.aggregate( [
          { $match: { _id: mongoose.Types.ObjectId(userId )} },
          { $unwind: "$notifications" },
          { $replaceRoot: { newRoot: '$notifications' } }
    ] );
    

    or you can go the long way without using the utility functions :P
    playground

    const notifications = await this.userRepo.aggregate( [
          { $match: { $expr: { $eq: [ "$_id", { $toObjectId: userId } ] } } },
          { $unwind: "$notifications" },
          { $replaceRoot: { newRoot: '$notifications' } }
    ] );