2013-05-09 65 views
0

餐廳 的has_many菜複雜的Rails/Postgres的SQL優化

Dish 
has_many Photo 

Photo 
belongs_to Dish 

Restaurant 1 
    Dish 1 
    Photo 1 May 9, 1:00 PM 
    Dish 2 
    Photo 2 May 9, 2:00 PM 
    Dish 3 
    Photo 3 May 9, 3:00 PM 

Restaurant 2 
    Dish 4 
    Photo 4 May 9, 1:00 PM 
    Dish 5 
    Photo 5 May 9, 2:00 PM 
    Dish 6 
    Photo 6 May 9, 3:00 PM 

我想以每2張餐廳菜照片的限制檢索最新的50張照片。鑑於上述數據,我將能夠檢索帶ID的照片2, 3, 5, and 6

我目前的實施是醜陋至少可以說。

hash = {} 
bucket = [] 
Photo.includes(:dish => [:restaurant]).order("created_at desc").each do |p| 
    restaurant_id = p.dish.restaurant.id 
    restaurant_count = hash[restaurant_id].present? ? hash[restaurant_id] : 0 
    if restaurant_count < 2 
    bucket << p 
    hash[restaurant_id] = restaurant_count + 1 
    end 
    # if you've got 50 items short circuit. 
end 

我不禁覺得有更高效的解決方案。任何想法,將不勝感激 :-)。

+1

這是不落實,即使在純SQL瑣碎的邏輯。您可能會更好地維護某種特定的隊列結構,並始終保留這50張照片的列表。然後,您可以在灌注新照片時按2餐限制進行限制。很顯然,這將針對少數寫入多讀的內容進行優化。 – mikeryz 2013-05-09 14:45:21

+0

是的,那是我的下一步,因爲在子查詢中我真的很無能。 – lemon 2013-05-09 15:04:07

+0

如果您因爲某些Google搜索結果設置了SQL,而出現類似如下的情況:http://books.google.com/books?id=thTju-4duY4C&lpg=PP1&ots=nFmsRSwKu0&dq=enterprise%20rails&pg=PA147#v=onepage&q&f = false可能是最好的方法... – mikeryz 2013-05-09 15:22:12

回答

1

應該有「」分組查詢的一種方式,但至少下面是一個簡單一點:

def get_photo_bucket 
    photo_bucket = restaurant_control = [] 
    Photos.includes(:dish => [:restaurant]).order("created_at desc").each do |photo| 
    if photo_bucket.count < 50 && restaurant_control.count(photo.dish.restaurant.id) < 2 
     photo_bucket << photo 
     restaurant_control << photo.dish.restaurant.id 
    end 
    end 
    photo_bucket 
end 
+0

不幸的是,這隻會返回每家餐廳的最新兩道菜,而不是最近的兩道菜,每個餐廳最多隻有兩道菜。 – mikeryz 2013-05-09 14:40:45

+0

對不起@mikeryz,我誤解了你的約束。我編輯了答案。 – Galen 2013-05-09 14:52:50