Mongoid Group By or MongoDb on rails

I have a mongo table that has statistics like the following ....

so my class is as follows.

 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 

I want to get a daily count of the total number of plays for the course. So, for example ... 8/1/12 played 2 games, 8/2/12 played 6 matches. Etc. So I would use the timestamp created_at field, with id_path and action. The problem is that I do not see the group by method in Mongoid. I believe mongodb has one now, but I'm not sure how it will be done in rails 3.

I could run a table using each and hack a map or hash in rails with an increase, but what if the course has 1 million views, extracting and iterating over a million records can be dirty. Is there a clean way to do this?

+3
source share
2 answers

As pointed out in the comments, you can use map / reduce for this purpose. That way you can define the following method in your model ( 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 

which will result in the following result:

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

where _id is course_id and count is the number of pieces.

MongoDB also has a special group method, but I'm not sure how to get into the bare mongodb collection in Mongoid 3. I had no chance to dive even further into the code.

You may wonder why I am emitting the document {count: 1} since it is not a big deal, and I could just release an empty document or something else, and then always add 1 to result.count for each value. The fact is that the reduction is not called if only one of them was made for a specific key (in my example, course_id was played only once), so it is better to select documents in the same format as the result.

+8
source

Using Mongoid

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

OR

 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}) 

Follow the links below to group with mongoid

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

+3
source

All Articles