Агрегатные функции с MongoDB / Mongoid и вычисляемыми полями - PullRequest
3 голосов
/ 24 марта 2011

Я перевожу существующее приложение Rails для использования MongoDB (с Mongoid), и у меня возникают некоторые затруднения с выяснением, как выполнять агрегирование, как вы можете сделать с MySQL.

Раньше у меня было что-то вроде 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

Ответы [ 2 ]

5 голосов
/ 25 марта 2011

К сожалению, это немного сложнее, чем вы думаете.

Насколько я понимаю, сам 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 голосов
/ 26 апреля 2012

Mongoid также имеет несколько горячих клавиш для простых вычислений:

Вы можете добавить следующее к любой области:

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

Обратите внимание, что это не будет так быстро, как м / г дляон проходит через курсор в приложении против монго.Но если ваш результирующий набор не так уж и велик, это хороший вариант

Вот источник: https://github.com/mongoid/mongoid/blob/2.4.0-stable/lib/mongoid/contexts/enumerable.rb

Также следите за новостями о предстоящей структуре агрегации: http://www.mongodb.org/display/DOCS/Aggregation+Framework

...