Както бе споменато в коментарите, можете да използвате 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}}]
където _id
е course_id
и count
е броят на възпроизвежданията.
Има и специален групов метод в MongoDB, но не съм сигурен как да стигна до голата колекция mongodb в Mongoid 3. Все още нямах възможност да се гмуркам толкова много в кода.
Може да се чудите защо изпращам документ {count: 1}
тъй като няма толкова голямо значение и можех просто да изпусна празен документ или нещо друго и след това винаги да добавя 1 към резултата.брой за всяка стойност. Работата е там, че редуцирането не се извиква, ако е направено само едно излъчване за конкретен ключ (в моя пример course_id
е играно само веднъж), така че е по-добре да се излъчват документи в същия формат като резултата.