【问题标题】:Mongoid Group By or MongoDb group by in rails轨道中的 Mongoid Group By 或 MongoDb group by
【发布时间】:2012-08-17 22:29:23
【问题描述】:

我有一个 mongo 表,其中包含如下统计数据......

所以我的班级如下...

class Statistic
  include Mongoid::Document
  include Mongoid::Timestamps
  include Mongoid::Paranoia

  field :course_id, type: Integer
  field :status, type: String # currently this is either play or complete

我想获得一门课程的每日总播放次数。所以例如... 2012 年 8 月 1 日有 2 场,2012 年 8 月 2 日有 6 场。等等。因此,我将使用 created_at 时间戳字段,以及 course_id 和 action。问题是我在 Mongoid 中没有看到按方法分组。我相信 mongodb 现在有一个,但我不确定如何在 rails 3 中完成。

我可以使用每一个来遍历表,并在 Rails 中添加一些地图或哈希并增加增量,但如果课程有 100 万个视图,那么检索和迭代超过 100 万条记录可能会很麻烦。有没有干净的方法来做到这一点?

【问题讨论】:

  • 大约有 3 件错误/可疑之处:1) 你为什么使用 mongo 来做这个?不要说“因为它很酷”; 2) mongo 中的分组通常是通过 map/reduce 完成的,而不是像在 RDBMS 支持的应用程序中那样通过调用完成; 3) 该课程现在有 100 万次观看吗?如果没有,并且在 ruby​​ 中聚合很简单,那就去做吧。如果/何时出现规模,请担心规模。
  • 如果你可以使用2.2那么你可以使用聚合框架。

标签: ruby-on-rails ruby-on-rails-3 mongodb mongoid ruby-on-rails-3.2


【解决方案1】:

如 cmets 中所述,您可以为此目的使用 map/reduce。所以你可以在你的模型中定义以下方法(http://mongoid.org/en/mongoid/docs/querying.html#map_reduce

def self.today
  map = %Q{
    function() {
      emit(this.course_id, {count: 1})
    }
  }

  reduce = %Q{
    function(key, values) {
      var result = {count: 0};
      values.forEach(function(value) {
        result.count += value.count;
      });
      return result;
    }
  }

  self.where(:created_at.gt => Date.today, status: "played").
    map_reduce(map, reduce).out(inline: true)
end

这将导致以下结果:

[{"_id"=>1.0, "value"=>{"count"=>2.0}}, {"_id"=>2.0, "value"=>{"count"=>1.0}}] 

其中_idcourse_idcount 是播放次数。

MongoDB 中还有专用的 group 方法,但我不确定如何访问 Mongoid 3 中的裸 mongodb 集合。我还没有机会深入研究代码。

您可能想知道为什么我会发出一个文档 {count: 1},因为这并不重要,我可以只发出一个空文档或任何东西,然后总是为每个值的 result.count 添加 1。问题是,如果只对特定键进行了一次发射(在我的示例中,course_id 只播放了一次),则不会调用 reduce,因此最好以与结果相同的格式发射文档。

【讨论】:

    【解决方案2】:

    使用 Mongoid

    stages =  [{ 
             "$group" => {  "_id" => { "date_column_name"=>"$created_at" }},
             "plays_count" => { "$sum" => 1 }
        }]
    @array_of_objects = ModelName.collection.aggregate(stages, {:allow_disk_use => true})
    

    stages =  [{ 
              "$group" => {  
                 "_id" => { 
                           "year" => { "$year" => "$created_at" },
                           "month" => { "$month" => "$created_at" },
                           "day" => { "$dayOfMonth" => "$created_at" }
                  }
               },
              "plays_count" => { "$sum" => 1 }
        }]
    @array_of_objects = ModelName.collection.aggregate(stages, {:allow_disk_use => true})
    

    按照下面的链接使用 mongoid 进行分组

    https://taimoorchangaizpucitian.wordpress.com/2016/01/08/mongoid-group-by-query/ https://docs.mongodb.org/v3.0/reference/operator/aggregation/group/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-20
      • 1970-01-01
      • 2016-04-29
      相关资源
      最近更新 更多