2011-03-10 8 views
15

Raylar 3 mongoid ile kullanıyorum.Gömülü nesneleri Mongoid/raylar içinde sorgulama 3 ("Alttan", Min operatörler ve sıralama)

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 

Kimin minimum fiyat belirli bir tarih belirli bir fiyat p daha düşük olduğu için stoklarını olsun ister ve sonra sıralamak mümkün olacaktır: Ben Fiyatlarının gömülü koleksiyonu ile Stoklar bir koleksiyona sahip her bir hisse senedi için fiyatlar.

Ancak Mongodb'un buna izin vermediği anlaşılıyor. bu işe yaramaz çünkü:

@stocks = Stock.Where(:prices.value.lt => p) 

Ayrıca, mongoDB sıralama nesneleri gömülü olamaz gibi görünüyor.

Bu görevi yerine getirmek için bir alternatif var mı? i kolayca aşağıdaki sorguyu çalıştırabilir böylece

Belki bir koleksiyonunda her şeyi koymak gerekir:

@stocks = Stock.Where(:prices.lt => p) 

Ama gerçekten bir dizi benim sorgusunun ardından stok adlarına göre gruplanmış sonuçları (farklı stokları almak istiyorum örneğin sipariş edilen fiyatlar). Harita işlevini duydum/grup işlevini azalttım ancak Mongoid ile doğru şekilde nasıl kullanacağımı bilmiyorum. Yardımlarınız için

SELECT name, code, min(price) from Stock WHERE price<p GROUP BY name, code 

Teşekkür:

http://www.mongodb.org/display/DOCS/Aggregation

SQL eşdeğer böyle bir şey olurdu.

scope :greater_than, lambda {|value| { :where => {:value.gt => value} } } 

Bu, herhangi içinde geçmesine izin edecektir:

cevap

20

MongoDB/Mongoid bunu yapmak izin veriyoruz. Örnek çalışacak, sözdizimi yanlış.

@stocks = Stock.Where(:prices.value.lt => p) #does not work 

@stocks = Stock.where('prices.value' => {'$lt' => p}) #this should work 

Ve yine siz de ismen sipariş edebilirsiniz böylece chainable oluyor: Bu yardımcı olur

@stocks = Stock.where('prices.value' => {'$lt' => p}).asc(:name) 

Umut.

+0

Daha karmaşık sorgular hala yapılabilir, bunun gibi: 'all_of ({: 'books.name' => 'name'}, {: 'books.author' =>/joe/i})' –

1

MongoDB Ne kaçırdığını Fiyat modeline bir kapsam, böyle bir şey http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-ValueinanEmbeddedObject

olduğunu gömülü belgelerin sorgulama izin vermez istediğiniz değerden daha büyük bir değerle Mongoid koleksiyonu toplayın ve geri gönderin. Sıralanmamış bir koleksiyon olacak, böylece Ruby'de sıralamanız gerekecek.

prices.sort {|a,b| a.value <=> b.value}.each {|price| puts price.value} 

Mongoid bir map_reduce harita/azaltmak yürütmek için JavaScript fonksiyonlarını içeren iki dize değişkenleri geçmek yöntemi var, ve bu muhtemelen neye ihtiyacınız yapmanın en iyi yolu, ancak yukarıdaki kod olurdu şimdilik çalışacak.

+0

Cevabınız için teşekkür ederiz. Ama bu kapsam işlevselliğini nasıl kullanacağımdan emin değilim. Fiyat işlevimde kapsam işlevini koydum ve @Stocks = Stock.where (: prices.greater_than => 200) sorguladım, bana bir hata veriyor: "undefined method" için_sayfa: ': fiyatlar: Symbol " – mathieurip

+0

Kapsam Koleksiyonda değil, tek bir Stokta çağrılmalıdır. Yani, kodunuz gerçekten işe yaramaz. Bunu filtrelemek istediğin için MapReduce aramasında en iyisisin. Bir yerlere örnek göndereyim göreceğim. –

+0

Evet, bu sadece anladım. Yine de, fiyatlar 100 ile 200 arasında olan stokların listesini almak için işe yarayan aptalca ve yavaş bir çözüm buldum, ama ben bundan memnun değilim: i = 100 i <200 results = Stock.where ("prices.value" => i) (@stocks == nil) @stocks = sonuçlar + = sonuçlanır başka @stocks i greater_than kapsamı ucu sadece bir + = 1 sonu ' – mathieurip

2

Ben benzer bir sorun yaşadım ... Burada önerim var:

scope :price_min, lambda { |price_min| price_min.nil? ? {} : where("price.value" => { '$lte' => price_min.to_f }) } 

Yeri ebeveyn modelinde bu kapsamı. Aslında orada bazı verileri eklediğinizde benim kapsamı çalışır

Stock.price_min(1000).count 

Not: Bu gibi sorguları yapmak sağlayacaktır. Mongoid ile karmaşık sorgular oluşturuyorsanız bu çok kullanışlıdır.

İyi şanslar!Çok iyi

, Ruy