我在集合中拥有具有以下结构的用户文档:
{ "_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”)的格式时,它仍然不起作用。
聚合管道中还有其他功能,但是我把它们拿出来了,我仍然得到错误。
如何让聚合函数在Dates上匹配?
答案 0 :(得分:6)
以下测试使用聚合框架来估计查询的逻辑等效项。
首先$展开数组,$ 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
答案 1 :(得分:0)
如下所示更正聚合匹配的类型:
{:$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
答案 2 :(得分:0)
我发现this short post对我有帮助。这是基本的代码示例-比较起来似乎很简单:
Stat.collection.aggregate({
'$match' => {
'$and' => [
{ 'day' => { '$gte' => from.to_date.mongoize } },
{ 'day' => { '$lte' => to.to_date.mongoize } }
]
},
})
致谢作者!
答案 3 :(得分:-2)
对于红宝石来说并不多,但如果你可以粘贴mongo shell,我可以提供帮助。
提示很少: 1.你正在使用elemMatch所以你应该使用$ unwind 2.之后你尝试使用$ match