Mongoid聚合$ match与Date对象不起作用? [英] Mongoid aggregation $match with Date objects not working?

查看:222
本文介绍了Mongoid聚合$ match与Date对象不起作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一个具有以下结构的集合中有用户文档:

I have User documents in a collection that have this structure:

{ "_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" )}
  ]
}

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

I can easily query these documents based on date:

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

根据日志:

操作:127.0.0.1:27017 COMMAND database = db command = { :count =>用户,:query => {活动 => { $ elemMatch => { date_time_创建的 => { $ gte => 2012-05-10 00:00:00 UTC, $ lt => 2012-07-12 00:00:00 UTC}}}}}(0.5260ms)

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:

However, when I'm trying to use the new aggregate function and $match based on the same criteria:

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

根据日志:

操作: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)

MOPED: 127.0.0.1:27017 COMMAND database=db command={:aggregate=>"users", :pipeline=>[{"$match"=>{:activities=>{"$elemMatch"=>{"date_time_created"=>{"$gte"=>Thu, 10 May 2012, "$lt"=>Thu, 12 Jul 2012}}}}}]} (0.6049ms)

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

"start_date" and "end_date" are Ruby Date objects and are essentially the same in both queries. However, when I look at the logs they are changed into different formats. When I try to force the format with something like start_date.strftime("%Y-%m-%d") it still doesn't work.

还有其他函数在聚合管道中,但是我将它们取出却仍然出现错误。

There are other functions in the aggregate pipeline, but I took them out and I still get the error.

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

How can I get the aggregate function working to match on Dates?

推荐答案

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

The following test uses the aggregation framework to approximate the logical equivalent of your query.

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

First $unwind the array, $match, then $group using $addToSet in case there are multiple array elements that match. Note that this is a lossy process, but this is acceptable if you only need the count or the ids.

希望有帮助。

test / unit / user_test.rb

test/unit/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

这篇关于Mongoid聚合$ match与Date对象不起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆