2012-03-02 133 views
2

我在Rails應用程序中遇到了困難的篩選問題。用戶想要使用標籤過濾項目。這不是問題,我只是使用命名範圍。但標籤出現在用戶可以選擇的框中,如下所示:使用AND和OR在Rails中進行篩選查詢

Size 
    [XS] 
    [S] 

Color 
    [Red] 
    [Blue] 

這些標籤位於「標籤集」中,標籤集包含多個標籤。

我的問題:當用戶想要縮小搜索範圍時,如何將多個過濾器查詢鏈接在一起?

當用戶從第一個框中選擇XS時,它應該單獨過濾該標籤上的結果集。當用戶選擇XS和S時,我們將添加到過濾器並獲得更多結果。仍然不存在命名作用域的問題。但是如果用戶想要過濾XS和S,然後從第二個盒子過濾紅色,會怎麼樣?那就是當事情變得毛茸茸的時候 - 我不能僅僅爲該標籤添加另一個Item.by_tag(「標記名」),它需要成爲我已有結果的標籤過濾器,從而縮小結果範圍。

同一標記框中的多個複選框 - 更多結果。在另一個標記框中檢查 - 結果較少。我試着爲每個tagset框做一個SELECT,然後在ruby中合併結果集,只顯示所有集合中的hit,但是打破了分頁,因爲我不知道會返回多少結果。感覺這需要是一個查詢,它可能是某種連接,但是我對SQL並不擅長,我無法弄清楚。這是架構的相關部分的樣子:

create_table "items" do |t| 
    t.string "title" 
end 

create_table "items_tags", :id => false do |t| 
    t.integer "item_id" 
    t.integer "tag_id" 
end 

create_table "tags" do |t| 
    t.string "title" 
    t.integer "tagset_id" 
end 

create_table "tagsets" do |t| 
    t.string "title" 
end 

回答

0

看來Rails沒有提供構建OR查詢的方法。所以你必須自己做。 根據模式,一個項目has_and_belongs_to_many:tags,對吧? 在Rails 2.3中,下面的named_scopes應該可以工作。如果你使用Rails 3,你需要重寫它。

named_scope :having_tags, lambda { |tagsets| {:joins => :tags, :select => "DISTINCT items.*", 
    :conditions => ([Array.new(tagsets.size, "tags.title IN (?)").join(' OR ')] + tagsets) } 

然後調用它像這樣:

Item.having_tags([['XS', 'S'], ['Red', 'Blue']]) 

我假設你使用MySQL。

+0

這很好。謝謝! – straffaren 2012-10-26 11:17:32