findOneAndUpdate query subdocuments

I have a collection of album documents like this:

[
{
_id: ObjectId(“6681e3a67077572b06828972”),
users: [{blocked: false, name: “Bill”], {blocked: true, name: “Gates”]],
maxUnblockedUserCount: 5
}
]

I want to push a user to the users array. This is only allowed if there aren’t too many unblocked users already in the users array, the limit set by the field maxUnblockedUserCount.

This is my update statement, however it does not take into account unblocked users:
Album.findOneAndUpdate(
{
_id: albumId,
$expr: {
$lt: [{ $size: “$users” }, “$maxUnblockedUserCount”],
},
},
{
$push: { users: { _id: userId, blocked: false} },
},
{ new: true }
)

You could use a $reduce operation on the array to calculate the blocked and non-blocked users per document:

Then filter based on that, this could get expensive in terms of computation if you’re looking at lots of data at once.

Other options that spring to mind:

  • Keep blocked and un-blocked users in two array to make the calculation simpler
  • Keep a total count as property of the document which simplifies it even more
  • Keep the block / unblock data in another collection and use $lookup as needed (again more computation to get the data)
2 Likes

I split the array into 2 to make calculations simpler. It works like a charm.

1 Like