Mongoid聚合$匹配Date对象不起作用?

我有一个具有这种结构的集合中的用户文档:

{ "_id" : ObjectId( "4fb54ef46d93b33b21003951" ), "activities" : [ { "id" : ObjectId( "4fd66f9001e7fe9f03000065" ), "type" : "checkin", "date_time_created" : Date( 1339453328000 )}, { "date_time_created" : Date( 1337351732000 ), "date_time_updated" : Date( 1337351952635 ), "id" : ObjectId( "4fb65e346d93b3fe77000000" )} ] } 

我可以根据日期轻松查询这些文档:

 User.where( :activities => { '$elemMatch' => { :date_time_created => { '$gte' => start_date, '$lt' => end_date } } } ).length 

根据日志:

MOPED:127.0.0.1:27017 COMMAND database = db command = {:count =>“users”,:query => {“activities”=> {“$ elemMatch”=> {“date_time_created”=> {“$ gte” => 2012-05-10 00:00:00 UTC,“$ lt”=> 2012-07-12 00:00:00 UTC}}}}}(0.5260ms)

我得到了我需要的结果。

但是,当我尝试使用基于相同条件的新聚合函数和$ match时:

 User.collection.aggregate( [ { "$match" => { :activities => { '$elemMatch' => { :date_time_created => { '$gte' => start_date, '$lt' => end_date } } } } } ]).length 

根据日志:

MOPED:127.0.0.1:27017 COMMAND database = db command = {:aggregate =>“users”,: pipeline => [{“$ match”=> {:activities => {“$ elemMatch”=> {“date_time_created” => {“$ gte”=>星期四,2012年5月10日,“$ lt”=>星期四,2012年7月12日}}}}}]}(0.6049ms)

“start_date”和“end_date”是Ruby Date对象,在两个查询中基本相同。 但是,当我查看日志时,它们会被更改为不同的格式。 当我尝试强制使用类似start_date.strftime(“%Y-%m-%d”)的格式时,它仍然不起作用。

聚合管道中还有其他function,但是我把它们拿出来了,我仍然得到错误。

如何让聚合函数在日期上匹配?

以下测试使用聚合框架来近似查询的逻辑等效项。

首先$解开数组,$ match,然后$ group使用$ addToSet,以防有多个匹配的数组元素。 请注意,这是一个有损的过程,但如果您只需要计数或ID,这是可以接受的。

希望这会有所帮助。

测试/单元/ user_test.rb

 require 'test_helper' class UserTest < ActiveSupport::TestCase def setup User.delete_all end test "user aggregate" do User.create( activities: [ { id: Moped::BSON::ObjectId("4fd66f9001e7fe9f03000065"), type: "checkin", date_time_created: Time.at(1339453328000) }, { date_time_created: Time.at(1337351732000), date_time_updated: Time.at(1337351952635), id: Moped::BSON::ObjectId("4fb65e346d93b3fe77000000") } ] ) start_date = Time.at(1339453328000) end_date = start_date + 24*60*60 assert_equal(1, User.where( :activities => { '$elemMatch' => { :date_time_created => { '$gte' => start_date, '$lt' => end_date } } } ).length) assert_equal(1, User.collection.aggregate( [ { '$unwind' => '$activities' }, { '$match' => { '$and' => [ { 'activities.date_time_created' => { '$gte' => start_date } }, { 'activities.date_time_created' => { '$lt' => end_date } } ] } }, { '$group' => { '_id' => '$_id', 'activities' => { '$addToSet' => '$activities' } } } ] ).length) end end 

正确的聚合匹配类型,如下所示:

 {:$match=>{ :created_at=>{:$gte=>2017-03-07 00:36:30 +0700}}} 

这意味着你应该使用方法:

 match_na = { '$match': {created_at: { '$gte': (Time.now-30.days) } } } 

请注意:不要使用Time.zone.now(因为输出它将是另一种格式)。 我非常肯定100%。 我需要3个小时。

再次:制作日期或时间格式,如下所示:

 2017-03-07 00:36:30 +0700 

不是这个:

 Mon, 03 Apr 2017 00:34:14 ICT +07:00 

或简单方法:使用方法mongoize

 (Date.today - 30.days).mongoize 

我找到了这篇简短的post ,这对我很有帮助。 这是必要的代码示例 – 相比之下似乎非常简单:

 Stat.collection.aggregate({ '$match' => { '$and' => [ { 'day' => { '$gte' => from.to_date.mongoize } }, { 'day' => { '$lte' => to.to_date.mongoize } } ] }, }) 

给作者的信用!

我没有太多的ruby,但如果你可以粘贴mongo shell,我可以帮忙。

有一些提示:1。你正在使用elemMatch所以你应该使用$ unwind 2.之后你尝试使用$ match