0

Can I return a boolean variable as per the conditions in a mongoose query? Example, while getting all notification of a user, I want to show if a notification is seen by the user or not.

I have this schema:

const notificationSchema = mongoose.Schema({
    userid: { type: mongoose.Schema.Types.ObjectId, ref:'User', require: true, unique: false },
    time: Number,
    type: Number,
    seenBy: {type: [String], default: []}      // can have very large number of values (user IDs)
}, {__v: false});

Now while getting the notifications array I want to get an extra field which seen which is true if a specific user exists in respective seenBy[] array of the field. such that I get the response object like 1 new notification [{userid: <someid>, time: ... <other fields> ..., seen: false}]

Thank you

3
  • you can use count(), for example if count of seenBy with a conditions is zero return true else return false Commented Jan 11, 2021 at 8:36
  • So this notification is created by one user but can be seen by many other users ? Is this correct ? Commented Jan 11, 2021 at 9:10
  • @PascalLamers right Commented Jan 11, 2021 at 9:27

2 Answers 2

3

You would have to run an aggregation operation in which you use the $setIsSubset operator on two arrays i.e. the [userId] and seenBy arrays which returns true when the first array is a subset of the second, including when the first array equals the second array, and false otherwise.

The first userid array should be a string array since you will be comparing the array with another of string type so you need to convert the ObjectId to string using $toString.

As an example, the following shows the query:

const userId = '5ffafefe288e7a58ff08226e'; // the user id input variable as a string, could be from req.params.id or req.query.userId etc
const notifications = await Notification.aggregate([
    { '$match': { userid: mongoose.Types.ObjectId(userId) } },
    { '$addFields': { 
        'seen': {
            '$setIsSubset': [
                [{ '$toString': '$userid' }],
                '$seenBy'
            ]
        }
    }}
]);
Sign up to request clarification or add additional context in comments.

3 Comments

@chrisdam thanks for the answer, but can I perform same functionality in find() query ?
@PratikAgarwal You can't achieve the same with find, however you can do the transformation on the client side rather than the server
what kind of changes? If not, I'll have to run 2 queries. That's bad 😔
1

You should try

async func () {
    const doesUserExit = await User.exists({ _id: userid });
}

Read more model.exists, will return true or false.

1 Comment

I used that, but I need an extra variable in the query so I wont have to run a loop whether it exists or not. I want all notifications, and a "seen: false" in the ones where called userid is not present in seenBy array

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.