Mongoid查询buffer_time的一个整数字段+ Time.now,它大于scheduled_at字段

时间:2014-07-27 16:28:39

标签: ruby-on-rails mongoid mongoid3

我有一个mongo模型,包含buffer_time(Integer)和scheduled_at(DateTime)字段。 我想要一个优化的查询来获取

(Time.now + buffer_time.minutes) > scheduled_at

这是模型AdministrationTask

{
                        :_id => BSON::ObjectId('53d5091870637330e84e0000'),
                :buffer_time => 60,
              :resident_name => "jegi",
               :scheduled_at => 2014-08-26 14:00:00 UTC,
                     :status => "open",
                 :updated_at => 2014-07-27 14:13:44 UTC
}

我可以用地图写这个但是它耗费了很多时间。

1 个答案:

答案 0 :(得分:0)

CRUD操作仅支持简单的比较和操作。 如果需要进行计算,建议使用聚合框架。 您仍应考虑简化架构, 喜欢通过将其值合并到scheduled_at的值来消除buffer_time字段。

以下是显示如何使用聚合框架执行所需操作的答案。 希望您喜欢它并且它可以帮助您了解聚合框架如何计算匹配的结果。

测试/单元/ administration_task_test.rb

require 'test_helper'
require 'pp'

class AdministrationTaskTest < ActiveSupport::TestCase
  def setup
    Mongoid.default_session.drop
  end
  test 'multiple tag references' do
    admin_task_data = {
        :buffer_time => 60,
        :resident_name => "jegi",
        :scheduled_at => Time.parse("2014-08-26 14:00:00 UTC"),
        :status => "open",
        :updated_at => Time.parse("2014-07-27 14:13:44 UTC")
    }
    AdministrationTask.create(admin_task_data)
    AdministrationTask.create(admin_task_data.merge(resident_name: 'xyzzy', scheduled_at: Time.now))
    puts "\nall administration tasks:"
    pp AdministrationTask.all.to_a
    run_now_tasks = AdministrationTask.collection.aggregate(
          {
              '$project' => {
                  '_id' => '$_id', 'buffer_time' => '$buffer_time', 'resident_name' => '$resident_name',
                    'scheduled_at' => '$scheduled_at', 'status' => '$status', 'updated_at' => '$updated_at',
                  'match' => {
                      '$gt' => [
                          {'$add' => [Time.now, {'$multiply' => ['$buffer_time', 1000]}]},
                          '$scheduled_at'
                      ]
                  }
              }
          },
          {
              '$match' => {'match' => true}
          }
      ).to_a
    puts "administration tasks to run now:"
    pp run_now_tasks
    assert_equal(1, run_now_tasks.size)
    assert_equal('xyzzy', run_now_tasks.first['resident_name'])
  end
  test '0. mongoid version' do
    puts "\nMongoid::VERSION:#{Mongoid::VERSION}\nMoped::VERSION:#{Moped::VERSION}"
  end
end

rake test

Run options:

# Running tests:

[1/2] AdministrationTaskTest#test_0._mongoid_version
Mongoid::VERSION:3.1.6
Moped::VERSION:1.5.2
[2/2] AdministrationTaskTest#test_multiple_tag_references
all administration tasks:
[#<AdministrationTask _id: 53f266bd7f11ba0f51000001, buffer_time: 60, resident_name: "jegi", scheduled_at: 2014-08-26 14:00:00 UTC, status: "open", updated_at: 2014-07-27 14:13:44 UTC>,
 #<AdministrationTask _id: 53f266bd7f11ba0f51000002, buffer_time: 60, resident_name: "xyzzy", scheduled_at: 2014-08-18 20:49:01 UTC, status: "open", updated_at: 2014-07-27 14:13:44 UTC>]
administration tasks to run now:
[{"_id"=>"53f266bd7f11ba0f51000002",
  "buffer_time"=>60,
  "resident_name"=>"xyzzy",
  "scheduled_at"=>2014-08-18 20:49:01 UTC,
  "status"=>"open",
  "updated_at"=>2014-07-27 14:13:44 UTC,
  "match"=>true}]
Finished tests in 0.524457s, 3.8135 tests/s, 3.8135 assertions/s.
2 tests, 2 assertions, 0 failures, 0 errors, 0 skips