我有一个使用Mongoid连接到MongoDB的模型事件:
class Event
include Mongoid::Document
include Mongoid::Timestamps
field :user_name, type: String
field :action, type: String
field :ip_address, type: String
scope :recent, -> { where(:created_at.gte => 1.month.ago) }
end
通常当我使用ActiveRecord时,我可以做类似的事情来分组结果:
@action_counts = Event.group('action').where(:user_name =>"my_name").recent.count
我得到的格式如下:
{"action_1"=>46, "action_2"=>36, "action_3"=>41, "action_4"=>40, "action_5"=>37}
使用Mongoid做同样事情的最佳方法是什么?
提前致谢
答案 0 :(得分:2)
我认为你必须使用map / reduce来做到这一点。请查看此SO问题以获取更多详细信息:
Mongoid Group By or MongoDb group by in rails
否则,您只需使用group_by
中的Enumerable
方法即可。效率较低,但除非你有数十万份文件,否则它应该可以解决问题。
编辑:在这种情况下使用map / reduce的示例
我对它并不熟悉,但通过阅读文档和玩游戏,我无法重现你想要的完全相同的哈希,但试试这个:
def self.count_and_group_by_action
map = %Q{
function() {
key = this.action;
value = {count: 1};
emit(key, value);
# emit a new document {"_id" => "action", "value" => {count: 1}}
# for each input document our scope is applied to
}
}
# the idea now is to "flatten" the emitted documents that
# have the same key. Good, but we need to do something with the values
reduce = %Q{
function(key, values) {
var reducedValue = {count: 0};
# we prepare a reducedValue
# we then loop through the values associated to the same key,
# in this case, the 'action' name
values.forEach(function(value) {
reducedValue.count += value.count; # we increment the reducedValue - thx captain obvious
});
# and return the 'reduced' value for that key,
# an 'aggregate' of all the values associated to the same key
return reducedValue;
}
}
self.map_reduce(map, reduce).out(inline: true)
# we apply the map_reduce functions
# inline: true is because we don't need to store the results in a collection
# we just need a hash
end
所以当你打电话时:
Event.where(:user_name =>"my_name").recent.count_and_group_by_action
应该返回类似的内容:
[{ "_id" => "action1", "value" => { "count" => 20 }}, { "_id" => "action2" , "value" => { "count" => 10 }}]
免责声明:我不是mongodb也不是mongoid专家,我的例子基于我在参考的SO问题和Mongodb / Mongoid在线文档中找到的内容,任何使这更好的建议都将受到赞赏。
资源:
http://docs.mongodb.org/manual/core/map-reduce/ http://mongoid.org/en/mongoid/docs/querying.html#map_reduce