Jak wspomniano w komentarzach, możesz użyć do tego celu map/reduce. Możesz więc zdefiniować następującą metodę w swoim modelu ( 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
co dałoby następujący wynik:
[{"_id"=>1.0, "value"=>{"count"=>2.0}}, {"_id"=>2.0, "value"=>{"count"=>1.0}}]
gdzie _id
to course_id
i count
to liczba odtworzeń.
Istnieje również dedykowana metoda grupowa w MongoDB, ale nie jestem pewien, jak dostać się do samej kolekcji mongodb w Mongoid 3. Nie miałem jeszcze okazji zagłębić się w kod.
Możesz się zastanawiać, dlaczego emituję dokument {count: 1}
ponieważ to nie ma większego znaczenia i mogłem po prostu wyemitować pusty dokument lub cokolwiek, a następnie zawsze dodać 1 do result.count dla każdej wartości. Chodzi o to, że Reduce nie jest wywoływane, jeśli tylko jeden emit został wykonany dla określonego klucza (w moim przykładzie course_id
został odtworzony tylko raz), więc lepiej jest emitować dokumenty w tym samym formacie, co wynik.