0

我有兩個模型,客戶和具有HABTM關聯的項目。我想找到最快的方法來選擇所有的客戶,其中有幾個(多個)項目(或一定數量的項目)。查詢兩個HABTM模型(Rails3)

class Client < ActiveRecord::Base 
    has_and_belongs_to_many :items 
end 

class Item < ActiveRecord::Base 
    has_and_belongs_to_many :clients 
end 

下面的查詢獲取客戶,其中有任何一個項目從列表:

required_item_ids = Item.where(:kind => :book).collect(&:id) 
Client.join(:items).where(:items => {:id => required_item_ids}) 

但需要的是具有所需物品的幾個或全部的客戶名單。

我相信這是一個簡單的問題,因爲我是Rails的新手,但是我在這裏和其他一些地方查看了所有類似的問題,但沒有找到答案。

+0

我不認爲你可以直接與AR做到這一點。您可能需要編寫自己的SQL(對於每個客戶端,選擇所有項目,然後檢查所選項目中是否包含required_items;如果是,則返回客戶端) – alste

回答

1

如果這是一次性工作,那麼您可以通過循環遍歷Ruby中的所有客戶端來獲取此列表。喜歡的東西:

clients_with_more_than_one_book_items = [] 
book_items = Item.where(:kind => :book) 

Client.find_each do |client| 
    books_count = 0 
    client.items.each do |item| 
    if book_items.include?(item) 
     books_count += 1 
    end 
    end 

    clients_with_more_than_one_book_items << client if books_count > 1 
end 

然而,這可能需要一段時間,如果你有很多的客戶和項目的運行,因此,如果這是你經常運行的查詢,它可能添加一個books_count一個好主意屬性添加到客戶端模型中,並添加代碼(在模型中的回調中),使其更新爲一種計數器緩存。

+0

謝謝Frankie。也想到這一點,但這是一個昂貴的查詢,我正在尋找更快的解決方案。如果沒有其他方法,使用計數器緩存似乎沒問題。 –