Basheer Nawab
Basheer Nawab

Reputation: 13

how to get count of unread messages against each user Mongoose

I want to select user list from users collection and if a user has an unread message which status is 0/false in messages schema then select unread messages count too, which can be 0/5/10/1/0. thanking you in advance! i am sure it can be done with aggregate framework and already tried some query(below) but with that i am not getting what i need to be the result.

//User Schema 
import mongoose from 'mongoose';

const userSchema = new mongoose.Schema({
 name: { type: String, required: true, trim: true },
 email:{type: String, required: true, unique: true, minlength: 3, trim: true},
 password: { type: String, required: true, minlength: 6, trim: true },
});

   export default mongoose.model('user', userSchema);

//Message Schema
import mongoose from 'mongoose';

const messageSchema = new mongoose.Schema({
    from: { type: mongoose.Schema.Types.ObjectId, ref: 'user' },
    to: { type: mongoose.Schema.Types.ObjectId, ref: 'user' },
    text: { type: String, trim: true },
    unread: { type: Boolean, default: false }
});
messageSchema.set('timestamps', true);

export default mongoose.model('message', messageSchema);

I want the result should be

[ { _id: 5cc984981fa38539f4a61ce0,
     name: 'Jhon Doe',
     unreadTotal: 5 },

   { _id: 5cc98f651fa38539f4a61cfd,
    name: 'Markas',
     unreadTotal: 3 },

   { _id: 5cc994b164745026c4e25546,
     name: 'Mike',
    unreadTotal: 0 } ]


   // i tried the following but getting unread of total not for each user
    const userId = 'loggedinUserId'
    const userList = await User.aggregate([
            {
                $match: { _id: {$ne: ObjectId(userId) } }
            },
            { $lookup: 
                {
                    from: 'messages',
                    let: { 'to': ObjectId(userId) },
                    pipeline: [
                        { 
                            $match: 
                            {
                                'unread': false,
                                $expr: { $eq: [ '$$to', '$to' ] }
                            }
                        },
                        { $count: 'count' }
                    ],
                    as: 'messages'    
                }
            },
            { 
                $addFields: 
                {
                    'unreadTotal': { $sum: '$messages.count' }
                }
            }
          ]);

Upvotes: 1

Views: 1350

Answers (1)

Alamgir Khan
Alamgir Khan

Reputation: 46

Not sure this will help you or not, but you will get all unread messages of each user against the logged in user as you have described and later you can do whatever you want with like count etc.

const userList = await User.aggregate([
            {
                $match: { _id: {$ne: ObjectId(userId) } }
            },
            { 
                $lookup: 
                {
                    from: 'messages',
                    localField: '_id',
                    foreignField: 'from',
                    as: 'messages'
                },
            },
            {
                $project: 
                {
                    name: 1,
                    email: 1,
                    profilePhoto: 1,
                    messages: 
                    { 
                        $filter: 
                        { 
                            input: "$messages", 
                            as: "message", 
                            cond: { 
                                $and: [
                                    { $eq: [ '$$message.unread', false ] },
                                    { $eq: [ '$$message.to', ObjectId(userId) ] }
                                ]
                            }
                        }
                    }
                }
            }
        ]);

Upvotes: 1

Related Questions