Question

I have this dataset stored in Mongo. Each element has a created_at attributed.

MyModel.all
=> [#<MyModel _id: "bson_object10", created_at: 2014-04-04 16:19:29 UTC, type: "source",     updated_at: 2014-04-04 16:20:12 UTC>,
 #<MyModel _id: "bson_object11", created_at: 2014-04-04 16:19:29 UTC, type: "source",  updated_at: 2014-04-04 16:20:12 UTC>,
 #<MyModel _id: "bson_object12", created_at: 2014-04-04 16:19:29 UTC, type: "source", updated_at: 2014-04-04 16:20:12 UTC>,
 #<MyModel _id: "bson_object20", created_at: 2014-04-04 16:19:30 UTC, type: "source", updated_at: 2014-04-04 16:20:12 UTC>,
 #<MyModel _id: "bson_object21", created_at: 2014-04-04 16:19:30 UTC, type: "source", updated_at: 2014-04-04 16:20:12 UTC>,
 #<MyModel _id: "bson_object22", created_at: 2014-04-04 16:19:30 UTC, type: "source", updated_at: 2014-04-04 16:20:12 UTC>,
 #<MyModel _id: "bson_object30", created_at: 2014-04-04 16:19:31 UTC, type: "source", updated_at: 2014-04-04 16:20:12 UTC>,
 #<MyModel _id: "bson_object31", created_at: 2014-04-04 16:19:31 UTC, type: "source", updated_at: 2014-04-04 16:20:12 UTC>,
 #<MyModel _id: "bson_object32", created_at: 2014-04-04 16:19:31 UTC, type: "source", updated_at: 2014-04-04 16:20:12 UTC>]

My goal is to filter by time. To do that I have a time window

Time.at(payload_range[:start_time].to_i).utc
=> 2014-04-04 16:19:29 UTC

Time.at(payload_range[:end_time].to_i).utc
=> 2014-04-04 16:19:30 UTC

With that time window I would expect to retrieve the first 6 elements in my mongodb using this query:

MyModel.where(
   :created_at.gte => Time.at(payload_range[:start_time].to_i).utc,
   :created_at.lte => Time.at(payload_range[:end_time].to_i).utc
).count()
=> 3

But I get the first three. For some reason LTE is not working as expected and it is not including the elements at 2014-04-04 16:19:30 UTC.
What I am doing wrong?

Thank you

Was it helpful?

Solution

I would guess that you're having a problem with fractional seconds somewhere.

If I look at one of my documents inside the MongoDB shell, I see things like this:

"updated_at" : ISODate("2014-04-03T16:29:01.036Z"),

but when I look at from the Rails console I see:

updated_at: 2014-04-03 16:29:01 UTC

Of course, '2014-04-03T16:29:01.036' <= '2014-04-03T16:29:01' is false but the hidden 0.036s would make that result somewhat puzzling. So if I only look at the timestamps through Rails I might thing that an :updated_at.lte query against '2014-04-03T16:29:01' should find that document but it won't.

You could add one second and switch to lt:

MyModel.where(
   :created_at.gte => Time.at(payload_range[:start_time].to_i).utc,
   :created_at.lt  => Time.at(payload_range[:end_time  ].to_i).utc + 1.second
)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top