Mongoid date range query
I can't seem to find anything to make a date range query using Mongoid/Rails. Below are some queries I've tried (among about 100 others). If it returns anything, it always ignores the 'end_date'. Both dates are datetimes...
all(:conditions => {:created_at => start_date.to_datetime..end_date.to_datetime})
results in:
NoMethodError: unde开发者_如何学编程fined method `to_i' for Tue, 26 Apr 2011 00:00:00 +0000..Fri, 06 May 2011 00:00:00 +0000:Range
another example...
where(:created_at => {'$gte' => start_date,'$lt' => end_date})
results in a successful query but the end date is ignored. The results come back correctly after the start date but are not limited by the end date.
I've been working on this problem for several days to no avail. Not much help online, in the forums or IRC.
Would love to figure what I'm doing wrong :)
There was a bug in Mongoid. Fixed now.
For more information:
https://github.com/mongoid/mongoid/issues/761
https://github.com/mongoid/mongoid/commit/f326de5acc969e1342e640dc026de7e94bf4cf49#lib/mongoid/matchers.rb
I did a little research and came across the post Advanced Queries, in which one user asks:
Is there a better way to sort or query using datetime comparisons, than storing the date in Mongo as an integer of seconds since epoch? This is currently the only way that is working for me to do gte comparisons in Mongo to retrieve results.
Another user's reply to this:
Use the native BSON date type. Internally, it's a 64-bit integer of the number of milliseconds since epoch.
So you might want to approach this differently and convert between the number of milliseconds since epoch for your range queries. That way you're doing a simple gte/lt
on integers. The user's suggestion is relatively new (posted 3 months ago), so it may still be the most foolproof way to compare dates with Mongo in general (and thus Mongoid).
I used the MongoDB shell to test this:
Executed this several times
db.con.save({created: new Date()})
Then I got
> db.con.find()
{ "_id" : ObjectId("4dc3d380724a42d80d636b09"), "created" : ISODate("2011-05-06T10:54:56.809Z") }
{ "_id" : ObjectId("4dc3d383724a42d80d636b0a"), "created" : ISODate("2011-05-06T10:54:59.699Z") }
{ "_id" : ObjectId("4dc3d385724a42d80d636b0b"), "created" : ISODate("2011-05-06T10:55:01.543Z") }
{ "_id" : ObjectId("4dc3d38b724a42d80d636b0c"), "created" : ISODate("2011-05-06T10:55:07.043Z") }
{ "_id" : ObjectId("4dc3d38c724a42d80d636b0d"), "created" : ISODate("2011-05-06T10:55:08.168Z") }
{ "_id" : ObjectId("4dc3d49d4087861731076f8a"), "created" : ISODate("2011-05-06T10:59:41.755Z") }
As split date i choose ISODate("2011-05-06T10:55:00Z")
create this with d = new Date(2011,04,06,12,55,00)
The differences come since the month starts at zero and the time is utc time zone.
Now db.con.find({"created": {$gt:d}})
yields
{ "_id" : ObjectId("4dc3d385724a42d80d636b0b"), "created" : ISODate("2011-05-06T10:55:01.543Z") }
{ "_id" : ObjectId("4dc3d38b724a42d80d636b0c"), "created" : ISODate("2011-05-06T10:55:07.043Z") }
{ "_id" : ObjectId("4dc3d38c724a42d80d636b0d"), "created" : ISODate("2011-05-06T10:55:08.168Z") }
{ "_id" : ObjectId("4dc3d49d4087861731076f8a"), "created" : ISODate("2011-05-06T10:59:41.755Z") }
So MongoDb does everything correct. How to do that in Ruby is something I do not know.
精彩评论