Count a subdocument property in a projection using MongoDB and Javascript

Viewed 43

I've this document that represents a room with subRooms, and each subroom has notifications.

 [
      {
        _id: 1,
        id: 1,
        room: "Room1",
        subRoom: [
          {
            id: "SubRoom1",
            notifications: [
              {
                id: 1,
                read: []
              },
              {
                id: 2,
                read: []
              },
              {
                id: 3,
                read: []
              },
              {
                id: 4,
                read: []
              },
              {
                id: 5,
                read: []
              }
            ]
          },
          {
            id: "SubRoom2",
            notifications: [
              {
                id: 1,
                read: [
                  "User1"
                ]
              },
              {
                id: 2,
                read: [
                  "User1"
                ]
              },
              {
                id: 3,
                read: []
              },
              {
                id: 4,
                read: []
              },
              {
                id: 5,
                read: []
              }
            ]
          }
        ]
      }
    ]

Desired result: (I want to get the notification count if userId is not in notification.read, of every subroom)

[
  {
    "notRead": 3,
    "room": "Room1",
    "subRoom": [
      {
        "id": "SubRoom1",
        "notRead": 5
      },
      {
        "id": "SubRoom2",
        "notRead": 3
      }
    ]
  }
]

Playground with current code: https://mongoplayground.net/p/uJH9A6B-FQ7

Thank you very much in advance.

1 Answers
  • $map to iterate loop of subRoom array and in to return required fields
  • $filter to iterate loop of notifications and $size to get total elements from filtered result
db.collection.find({ id: 1 },
{
  _id: 0,
  room: 1,
  notRead: {
    $size: {
      $filter: {
        input: "$notifications",
        cond: {
          $not: { $in: ["User1", "$$this.read"] }
        }
      }
    }
  },
  "subRoom": {
    $map: {
      input: "$subRoom",
      in: {
        id: "$$this.id",
        notRead: {
          $size: {
            $filter: {
              input: "$$this.notifications",
              cond: { $not: { $in: ["User1", "$$this.read"] } }
            }
          }
        }
      }
    }
  }
})

Playground

Related