Meteor JS: Date Range Query in Mongo - mongodb

I have a collection that contains a dateAcquired attribute (which is from an XML API Feed the app is consuming).
I am trying to write a .find() query that will pull back all of the entries that are greater than or equal to 1 month ago from today.
The dateAcquired field date looks like: "dateAcquired": "2014-03-28 06:08 AM".
How to do that query in mongodb?

As Neil Lunn already stated, you should use timestamps for your dates in mongo.
More information to parse dates and so on are here
If you use timestamps, then you may use something like this as find selector over you mongo collection:
{dateacquired:{$gte: date_from, $lte: date_to}}
You can calculate the dates with momentjs (recommended) or whatever.

Related

Query mongodb for a specific date range

I've googled and googled this, and for the life of me I can't make it work...which I know I am just missing something totally simple, so I'm hoping someone here can save my sanity.
I have am trying to lookup a range of documents from a mongodb collection (using mongoose) based on a date range.
I have this code:
var startDate = new Date(req.query.startDate);
var stopDate = new Date(req.query.stopDate);
studentProgression.find({ $and: [ {'ACT_START': {$gte: startDate, $lte: stopDate} } ]})
But it doesn't return any documents.
The date in the MongoDb collection is stored as a string, and looks like this (for example):
ACT_START: "25-MAY-20"
a
I know I'm probaby tripping somewhere with the fact it's a string and not a date object in mongo, as I haven't had this issue before. I'd rather not go through the collection and change all the string dates to actual date objects.
Is there anyway to do this lookup the way I've laid it out?
Unfortunately, you have to change the format of your ACT_START field and cast it to a Date.
By doing $gte and/or $lte on a string field, mongo will compare the two strings based on their alphabetical order.

ISO8601 Date Strings in MongoDB (Indexing and Querying)

I've got a collection of documents in MongoDB that all have a "date" field, which is an ISO8601 formatted date string (i.e. created by the moment.js format() method).
I'd like to be able to efficiently run queries against this collection that expresses the sentiment "documents that have a date that is after A and before B" (i.e. documents within a range of dates).
Should I be storing my dates as something other than ISO-8601 strings? Contingent upon that answer, what would the MongoDB query operation look like for my aforementioned requirement? I'm envisioning something like:
{$and: [
{date: {$gt: "2017-05-02T03:15:22-04:00"}},
{date: {$lt: "2017-06-02T03:15:22-04:00"}},
]}
Does that "just work"? I need some convincing.
You definitely want to use the built-in date data type with an index on your date field and not strings. String comparison is going to be slow as hell compared to comparing dates which are just 64bit integers.
As far as querying is concerned, check out the answer here:
return query based on date

View last N documents using MongoDB Compass

I wish to view in MongoDB Compass the last N documents in a very large collection; too many to scroll through.
I could .skip(total - N) if I knew the syntax for that within Compass.
Alternatively, I have a date field and could use $gte with a date if I knew how to express a date in a manner acceptable to Compass.
Suggestion/example how to do this, please?
MongoDB Compass 1.6.1(Stable)
For date comparison you need to use $date operator with a string that represents a date in ISO-8601 date format.
{"date": {"$gte": {"$date": "2017-03-13T09:51:26.317Z"}}}
In my case the values of date field in Compass and mongo shell are different. So firstly I query the documents in the shell and then copy the "2017-03-13T09:51:26.317Z" from the result to the Compass filter line. In mongo shell it look like:
{
...
"date" : ISODate("2017-03-13T09:51:26.317Z"),
...
}
MongoDB Compass 1.7.0-beta.0 (Beta)
This version have an advanced query bar that lets you input not just the filter (as before), but also project, sort, skip and limit
(#Oleksandr I learned from your effective answer; thank you.)
I've also been shown that the Compass Schema tab allows one to drag a date range on the _id field to apply a filter query for that range. That range can be successively narrowed as desired.
Skip is descibed here
https://docs.mongodb.com/compass/current/query/skip/
In the Query Bar, click Options.
Enter an integer representing the number of documents to skip into the Skip field
Click Find to run the query and view the updated results.

Querying on Date in Mongo

I'm inserting a Mongo doc with the following time-stamp:
val format = new java.text.SimpleDateFormat("yyyyMMddHHmmss")
format.format(new Date()).toLong
Here's what the section looks like from Mongo's shell:
"{Timestamp" : NumberLong("20130919161948")}"
Based on a few tests, it appears to me that I can simply compare 2 documents by Timestamp by simply checking > or < for the yyyyMMddHHmmss format.
Please let me know if this time-stamp is OK for Mongo. Will I be able to query with it?
Mongo will not understand this as a timestamp, but as a number. As you set your date with a format going from year to seconds, you will be able to query mongo using > or < to know if it is before or after.
However if you want to mongo to treat the data as a date, you will need to use the appropriate bson date format. By having mongo treat it as a date, you will have all Mongo date operations available, like extracting year, day of week, etc.. read more
If you are using casbah, and Joda, you can enable serialization and deserialization by an explicit call:
import com.mongodb.casbah.conversions.scala._
RegisterJodaTimeConversionHelpers()
Read more here.
#Kevin, I think you are right. java.util.Date is supported in BSON object.
Using NumberLong to represent timestamp allows you to do range queries, but with BSON date type, date operation in aggregation framework becomes possible, which is more powerful.

Using future dates with Mongo TTL

we are currently experimenting with Mongo's new TTL feature and would like records to expire based on a date that is in the "future" as of the creation time of the record. This is so different records can have different periods of validity.
For example, something like this:
db.createCollection("sushi")
db.sushi.ensureIndex({"best_before": 1}, {expireAfterSeconds: 1})
db.sushi.insert({name: "ngiri", best_before: new Date('2012/10/02')})
But in our initial tests documents do not get removed from the collection if the indexed date field is in the future at the time of the creation of the record.
Is there any reason why this shouldn't work?
Thanks
Looks like it was daylight saving that go me here. Lesson learnt.