Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

MongoDB Aggregation Query Leap Year

I have a problem with queries.

Consider these documents:

{
    "_id" : ObjectId("63a994974ac549c5ea982d2b"),
    "title" : "Destroyer",
    "year" : 2018
},
{
    "_id" : ObjectId("63a994974ac549c5ea982d2a"),
    "title" : "Aquaman",
    "year" : 2014
},

{
    "_id" : ObjectId("63a994974ac549c5ea982d29"),
    "title" : "On the Basis of Sex",
    "year" : 1996   
},

{
    "_id" : ObjectId("63a994974ac549c5ea982d28"),
    "title" : "Holmes and Watson",
    "year" : 1940
},
{
    "_id" : ObjectId("63a994974ac549c5ea982d27"),
    "title" : "Conundrum: Secrets Among Friends",
    "year" : 1957
},
{
    "_id" : ObjectId("63a994974ac549c5ea982d26"),
    "title" : "Welcome to Marwen",
    "year" : 2004
},

{
    "_id" : ObjectId("63a994974ac549c5ea982d25"),
    "title" : "Mary Poppins Returns",
    "year" : 1997
},

{
    "_id" : ObjectId("63a994974ac549c5ea982d24"),
    "title" : "Bumblebee",
    "year" : 2004
}

I am trying to group all leap years in these documents. I tried this code:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

var query0 = {$group: {"_id": {"year": "$year"}}}

var query1 = {$addFields: {
      leap: {
        "$and": [
          {"$eq": [{"$mod": ["$year",4]}, 0]},
          {"$or": [
              {"$ne": [{"$mod": ["$year", 100]}, 0]},
              {"$eq": [{"$mod": ["$year", 400]}, 0] }
          ]}
        ]
      }
}}

var query2 = {$project: {leap: true}}

var query3 = {$group: {
      "_id": "$leap",
      "count": {$sum: 1}
  }}

var etapas =  [query0, query1, query2, query3]

db.genres.aggregate(etapas)

But I get this output:

{
    "_id": false,
    "count": 8 
}

It is wrong because the expect output is this:

{
    "_id": Leap,
    "count": 3
}

I do not know what I am doing wrong.. but I cannot get the right output.

How can I fix this?

Thanks so much for your attention on me.

>Solution :

Based on your query, you will lose the $year field after the first $group stage.

  1. In the $group stage, add the year field.

  2. (Optional) The $project stage seems unnecessary.

  3. $group – You should conditionally sum the leap when $leap is true.

db.collection.aggregate([
  {
    $group: {
      "_id": {
        "year": "$year"
      },
      year: {
        $first: "$year"
      }
    }
  },
  {
    $addFields: {
      leap: {
        "$and": [
          {
            "$eq": [
              {
                "$mod": [
                  "$year",
                  4
                ]
              },
              0
            ]
          },
          {
            "$or": [
              {
                "$ne": [
                  {
                    "$mod": [
                      "$year",
                      100
                    ]
                  },
                  0
                ]
              },
              {
                "$eq": [
                  {
                    "$mod": [
                      "$year",
                      400
                    ]
                  },
                  0
                ]
              }
            ]
          }
        ]
      }
    }
  },
  {
    $group: {
      "_id": "Leap",
      "count": {
        $sum: {
          $cond: {
            if: {
              $eq: [
                "$leap",
                true
              ]
            },
            then: 1,
            else: 0
          }
        }
      }
    }
  }
])

Demo @ Mongo Playground


Or get the year value from _id.

db.collection.aggregate([
  {
    $group: {
      "_id": "$year"
    }
  },
  {
    $addFields: {
      leap: {
        "$and": [
          {
            "$eq": [
              {
                "$mod": [
                  "$_id",
                  4
                ]
              },
              0
            ]
          },
          {
            "$or": [
              {
                "$ne": [
                  {
                    "$mod": [
                      "$_id",
                      100
                    ]
                  },
                  0
                ]
              },
              {
                "$eq": [
                  {
                    "$mod": [
                      "$_id",
                      400
                    ]
                  },
                  0
                ]
              }
            ]
          }
        ]
      }
    }
  },
  {
    $group: {
      "_id": "Leap",
      "count": {
        $sum: {
          $cond: {
            if: {
              $eq: [
                "$leap",
                true
              ]
            },
            then: 1,
            else: 0
          }
        }
      }
    }
  }
])
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading