Mongo查询时间窗口没有返回预期的结果

时间:2014-04-04 20:44:23

标签: ruby mongodb mongomapper

我将此数据集存储在Mongo中。每个元素都有一个created_at属性。

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>]

我的目标是按时间过滤。要做到这一点,我有一个时间窗口

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

使用该时间窗口,我希望使用此查询检索我的mongodb中的前6个元素:

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

但是我得到了前三个。出于某种原因,LTE没有按预期工作,并且不包括 2014-04-04 16:19:30 UTC 的元素。
我做错了什么?

谢谢

1 个答案:

答案 0 :(得分:1)

我猜你在某个地方遇到了小数秒的问题。

如果我查看MongoDB shell中的一个文档,我会看到如下内容:

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

但是当我从Rails控制台查看时,我看到:

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

当然,'2014-04-03T16:29:01.036' <= '2014-04-03T16:29:01'是假的,但隐藏的0.036s会让这个结果有点令人费解。因此,如果我只通过Rails查看时间戳,我可能会对:updated_at.lte '2014-04-03T16:29:01'查询该文档但是它不会发现。

您可以添加一秒并切换到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
)