2011-03-24 64 views
3

我遷移現有的Rails應用程序使用MongoDB的(與Mongoid),和我有一些麻煩搞清楚如何做聚合一樣可以與MySQL做。用的MongoDB/Mongoid集合函數和計算領域

以前我有這樣的事情SELECT DATE(created_at) AS day, SUM(amount) AS amount GROUP BY day,這將返回一個集合,您可以通過在模板中像這樣的循環:

:day => '2011-03-01', :amount => 55.00 
:day => '2011-03-02', :amount => 45.00 
etc... 

有誰知道怎麼做,在Mongoid?該模型非常簡單:

class Conversion 
    include Mongoid::Document 
    include Mongoid::Timestamps 

    field :amount,  :type => Float, :default => 0.0 
    ... 
    # created_at generated automatically, standard Rails... 
end 

謝謝!

-Avishai

回答

5

不幸的是,它比你會覺得有點困難。

我的理解是,Mongoid本身不支持分組和另外一個查詢,這樣做 - 你需要做的地圖/直接與MongoDB的司機減少。我用一個類似的數據結構來運行這個例子,但是在翻譯過程中可能會有一些錯誤,如果您有任何問題,請告訴我,我會嘗試修改它。

首先,你需要定義你的地圖和減少功能。這些必須存儲爲JavaScript字符串。

map = "function(){ emit(new Date(this.created_at.getYear(), this.created_at.getMonth(), this.created_at.getDate()), {amount: this.amount}); };" 
reduce = "function(key, values){ var sum = 0; values.forEach(function(doc){ sum += doc.amount; }); return {amount: sum};};" 

然後調用map_reduce直接的收集,在這種情況下:

Conversion.collection.map_reduce(map, reduce).find.to_a 

將返回哈希數組類似如下:

[{"_id"=>Sat Dec 13 13:00:00 UTC 0110, "value"=>{"amount"=>55.0}}, {"_id"=>Sat Jan 17 13:00:00 UTC 0111, "value"=>{"amount"=>45.0}}] 
+0

實際工作!更痛了一下,比標準的ActiveRecord樣式的查詢使用,因爲你要得到的結果爲'結果[「_ ID」] [「值」] [「量」]',但很酷:-) – Avishai 2011-03-27 12:45:47

0

Mongoid也有極少數快捷鍵簡單計算:

您可以添加以下任何SCOP E:

.max(:age) 
.min(:quantity) 
.sum(:total) 

注爲它循環通過遊標在應用VS在蒙戈這不會是一樣快,M/R。但是,如果你的結果集是沒有那麼大,它是一個很好的選擇

這裏是源:https://github.com/mongoid/mongoid/blob/2.4.0-stable/lib/mongoid/contexts/enumerable.rb

也敬請期待即將到來的聚合框架:http://www.mongodb.org/display/DOCS/Aggregation+Framework