Odpytywanie osadzonych obiektów w Mongoid/rails 3 ("Lower than", operatory Min i sortowanie)
Używam rails 3 z mongoid. Mam zbiór akcji z wbudowanym zbiorem cen:
class Stock
include Mongoid::Document
field :name, :type => String
field :code, :type => Integer
embeds_many :prices
class Price
include Mongoid::Document
field :date, :type => DateTime
field :value, :type => Float
embedded_in :stock, :inverse_of => :prices
Chciałbym uzyskać zapasy, których cena minimalna od danej daty jest niższa niż podana cena p, a następnie móc sortować ceny dla każdej akcji.
Ale wygląda na to, że Mongodb nie pozwala na to. Bo to nie zadziała:
@stocks = Stock.Where(:prices.value.lt => p)
Wydaje się również, że mongoDB nie może sortować osadzonych obiektów.
Więc, jest alternatywa w rozkaz do wykonania tego zadania ?
Może powinienem umieścić wszystko w jednym zbiorze, abym mógł łatwo uruchomić następujące zapytanie:
@stocks = Stock.Where(:prices.lt => p)
Ale naprawdę chcę, aby wyniki pogrupowane według nazw akcji po moim zapytaniu(różne zapasy z tablicą zamówionych cen na przykład). Słyszałem o map/reduce z funkcją group, ale nie jestem pewien, jak poprawnie z nią korzystać z Mongoid.
Http://www.mongodb.org/display/DOCS/Aggregation
Odpowiednik w SQL byłoby coś takiego:
SELECT name, code, min(price) from Stock WHERE price<p GROUP BY name, code
Dzięki za pomoc. 3 answers
MongoDB / Mongoid pozwala ci to zrobić. Twój przykład zadziała, składnia jest po prostu Niepoprawna.
@stocks = Stock.Where(:prices.value.lt => p) #does not work
@stocks = Stock.where('prices.value' => {'$lt' => p}) #this should work
I nadal jest Łańcuchowy, więc możesz zamówić również po nazwie:
@stocks = Stock.where('prices.value' => {'$lt' => p}).asc(:name)
Mam nadzieję, że to pomoże.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-07 20:44:07
Miałem podobny problem... oto co proponuję:
scope :price_min, lambda { |price_min| price_min.nil? ? {} : where("price.value" => { '$lte' => price_min.to_f }) }
Umieść ten zakres w modelu rodzica . To umożliwi Ci tworzenie zapytań takich jak:
Stock.price_min(1000).count
Zauważ, że mój zakres działa tylko wtedy, gdy faktycznie wstawisz tam pewne dane. Jest to bardzo przydatne, jeśli budujesz złożone zapytania za pomocą Mongoid.
Powodzenia!Very best, Ruy
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-30 04:13:17
MongoDB umożliwia odpytywanie osadzonych dokumentów, http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-ValueinanEmbeddedObject
Brakuje Ci lunety na modelu cenowym, coś w tym stylu:
scope :greater_than, lambda {|value| { :where => {:value.gt => value} } }
To pozwoli Ci przekazać dowolną wartość i zwrócić Mongoid zbiór cen o wartości większej niż to, co przekazałeś. To będzie niesortowana kolekcja, więc musisz ją uporządkować Ruby.
prices.sort {|a,b| a.value <=> b.value}.each {|price| puts price.value}
Mongoid ma metodę map_reduce , do której przekazujesz dwie zmienne łańcuchowe zawierające funkcje Javascript do wykonania map/reduce, i prawdopodobnie byłby to najlepszy sposób na zrobienie tego, czego potrzebujesz, ale powyższy kod będzie działał na razie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-10 19:37:40