4

我有一个 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

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

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

4

2 回答 2

8

如评论中所述,您可以为此目的使用 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_id并且count是播放次数。

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

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

于 2012-08-20T08:10:13.663 回答
4

使用 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/

于 2016-01-08T12:24:25.087 回答