使用Ruby驱动按timestamp过滤MongoDB时查询返回空结果如何解决
问题根因
你集合中存储的timestamp字段是毫秒级Unix时间戳的数值类型,而MongoDB Ruby驱动在执行查询时,会自动将Ruby的Time类型对象转换为BSON格式的UTC日期类型进行匹配,两者字段类型完全不同,因此无法命中任何文档,返回空结果。
解决方案
方案1:不修改现有数据,调整查询逻辑
查询时直接用毫秒级数值做匹配,将需要比较的Time对象转换为毫秒级时间戳整数即可:
- 第一条查询调整后:
connection[:collection].find({"timestamp"=>{"$lte"=>Time.now.to_i * 1000}}).to_a
- 第二条查询调整后:
# 直接匹配示例文档的数值即可 connection[:collection].find({"timestamp"=>{"$lte"=>1048636800000}}).to_a # 也可以保持原计算逻辑的写法 connection[:collection].find({"timestamp"=>{"$lte"=>Time.at(1048636800000/1000).to_i * 1000}}).to_a
- 第三条查询调整后:
connection[:collection].find({"timestamp"=>{"$lte"=>Time.parse("2003-03-26 05:30:00 +0530").to_i * 1000}}).to_a
方案2:调整数据存储格式,后续查询更便捷
如果后续需要频繁用时间类型做查询,可以把现有集合中的timestamp字段统一从数值类型转换为BSON日期类型,数据迁移示例如下:
connection[:collection].find.each do |doc| # 跳过已经是Time类型的文档,避免重复迁移出错 next if doc[:timestamp].is_a?(Time) connection[:collection].update_one( { _id: doc[:_id] }, { "$set" => { timestamp: Time.at(doc[:timestamp] / 1000) } } ) end
迁移完成后,你原来写的三条查询语句就可以正常命中文档,返回预期结果。
内容的提问来源于stack exchange,提问作者user3636388
相关产品推荐
相关产品推荐

