Search code examples
node.jsmongodbmongoosemongoose-schema

how to count two same property with different values in mongoose?


first, i should say that im new to mongoDB and mongoose ODM. my question: each document of my documents is something like this:

{
  "_id": {
    "$oid": "6353f73c97588e3864eaa635"
  },
  "text": "test!",
  "date": "10/22/2022, 2:52:52 PM",
  "isCompleted": false
}

they have isComplete property that can be true or false. now i want to count documents with isComplete: true or isComplete: false in just one query. and i want something like this result:

{completed: 4, notCompleted: 6}

i found that mongoose has a method called count and countDocuments. but with these methodes, i can do what i want in 2 queries. like this:

//body of an async function      
const completed = await mongoose.count({ isCompleted: true });
const notCompleted = await mongoose.count({ isCompleted: false });

i can not do something like this:

//body of an async function      
const counts = await mongoose.count({ isCompleted: true, isCompleted: false });

i searched a lot about this, but i couldnt find any solution. so whats your solution? do you have any suggestion? thanks for helping.


Solution

  • You can use aggregate with conditional grouping, but I'm not sure whether that will be faster than 2 separated count queries in a collection with big record set since you will essentially be loading ALL your records in the pipeline.

    db.collection.aggregate([
      {
        "$group": {
          "_id": null,
          "completed": {
            "$sum": {
              "$cond": [
                {
                  "$eq": [
                    "$completed",
                    true
                  ]
                },
                1,
                0
              ]
            }
          },
          "incomplete": {
            "$sum": {
              "$cond": [
                {
                  "$eq": [
                    "$completed",
                    false
                  ]
                },
                1,
                0
              ]
            }
          },
          "totalCount": {
            "$sum": 1
          }
        },
        
      }
    ])
    

    https://mongoplayground.net/p/RynsVsi9BEJ

    PS: aggregation always return an array, so you can use e.g. results[0].completed to get number of completed records.