Home > other >  How to find the length of an array by filtering by a parameter value in MongoDb
How to find the length of an array by filtering by a parameter value in MongoDb

Time:07-25

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 of seen 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}`);

Playground

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.

  • Related