Mongodb query specific month | year not date

How can I request a specific month in mongodb, and not in a date range, I need a month to make a list of client’s birthdays for the current month.

There will be something like this in SQL:

SELECT * FROM customer WHERE MONTH(bday)='09' 

Now I need to translate this to mongodb. Note. My dates are already stored in the MongoDate type, I used this thinking, which will work easily until then, but now I can not easily find how to do it.

+4
source share
3 answers

You can do this with aggregate using the $month statement:

 db.customer.aggregate([ {$project: {name: 1, month: {$month: '$bday'}}}, {$match: {month: 9}} ]); 
+4
source

With MongoDB 3.6 and later, you can use the $expr operator in a href = "https://docs.mongodb.com/manual/reference/method/db.collection.find/#db.collection.find" rel = "nofollow noreferrer "> find() . This allows you to create query expressions that compare fields from the same document at the $match stage. p>

 db.customer.find({ "$expr": { "$eq": [{ "$month": "$bday" }, 9] } }) 

For other versions of MongoDB, consider starting an aggregation pipeline that uses the $redact operator, since it allows you to include one pipeline, functionality with $project to create a field that represents the month of the date field and $match to filter out documents that match the given month status in September.

In the above example, $redact uses the $cond tenary operator as a means of providing a conditional expression that will create a system variable that does the editing. The logical expression in $cond will check for equality of the field of the date operator with the given value, if it matches, then $redact will return documents using the $$KEEP system variable, and otherwise using $$PRUNE .

Execution of the following pipeline should give the desired result:

 db.customer.aggregate([ { "$match": { "bday": { "$exists": true } } }, { "$redact": { "$cond": [ { "$eq": [{ "$month": "$bday" }, 9] }, "$$KEEP", "$$PRUNE" ] } } ]) 

This is similar to $project + $match , but you will need to select all the other fields that go into the pipeline:

 db.customer.aggregate([ { "$match": { "bday": { "$exists": true } } }, { "$project": { "month": { "$month": "$bday" }, "bday": 1, "field1": 1, "field2": 1, ..... } }, { "$match": { "month": 9 } } ]) 

With another alternative, albeit slow query, using the find() method with $where as:

 db.customer.find({ "$where": "this.bday.getMonth() === 8" }) 
+5
source

If you are concerned about performance, you may want to save the month data in a separate field in each document.

+1
source

All Articles