I was building a chat server, where i need to get the number of messages that is marked as seen : false . below is my schema
const ChatSchema = mongoose.Schema({
chatId: { type: String, required: true, unique: true },
messages: [
{
message: { type: String, required: true },
sendBy: { type: String, required: true },
sendTo: { type: String, required: true },
seen: { type: Boolean, default: false },
date: { type: Date, default: Date.now()}
},
],
})
I have tried the following code but it always returns 1
const unSeenCount=await Chat.find({ chatId: chatId },
{ messages : { $elemMatch : { seen : false } } })
console.log(`unseen count is ${unSeenCount.length}`);
i think it only gets the documents with the query { chatId: chatId }
CodePudding user response:
try using filter instead of find:
const unSeenCount=await Chat.filter({ chatId: chatId },
{ messages : { $elemMatch : { seen : false } } })
console.log(`unseen count is ${unSeenCount.length}`);
CodePudding user response:
You have to calculate from projection,
- use
findOne
method because you want one chat's messages count - check just
chatId
condition in the query - add projection
$filter
to iterate loop ofseen
array from messages and check is any false$size
to count to total elements in above-filtered array
const unSeenCount = await Chat.findOne(
{ chatId: chatId },
{
count: {
$size: {
$filter: {
input: "$messages.seen",
cond: { $eq: ["$$this", false] }
}
}
},
// add more fields if you need in the result.
}
);
console.log(`unseen count is ${unSeenCount.count}`);
CodePudding user response:
If you use $elemMatch
, it will return you all documents that satisfy that criteria. Therefore if document has an array that satisfy that criteria, the whole document will be returned. The MongoDB will not "count" how much appereances are there in an array.
Your query will return you either 0 or 1, depends if there is at least one message with seen : false
in an array or not.
You can use unwind
operation: MongoDB: Count of matching array elements . It will allow you to work with objects inside array in same way as with documents. It is not very efficient though, so if you have a lot of messages and you do this operation often, it can consume a lot of MongoDB resources. So if you need to do this (or similar operations) with messages frequently, it is better to create separate collection for messages.