2012-05-25 42 views
1

我需要從一個數組中進行where查詢,其中數組的每個成員都是一個「like」操作,這個操作是ANDed。例如:在一個數組中的rails中創建一個where查詢

SELECT ... WHERE property like '%something%' AND property like '%somethingelse%' AND ... 

這是很容易做到的使用ActiveRecord的where功能,但我不能確定如何先清理它。我顯然不能創建一個字符串並將其填充到where函數中,但似乎沒有辦法使用?

感謝

回答

6

建立你LIKE模式最簡單的方法是字符串插值:

where('property like ?', "%#{str}%") 

,如果您有陣列中所有的字符串,那麼你可以使用ActiveRecord的查詢鏈接和inject建立自己的最終查詢:

a = %w[your strings go here] 
q = a.inject(YourModel) { |q, str| q.where('property like ?', "%#{str}%") } 

然後你可以q.allq.limit(11)或任何你需要做的事情來獲得你的最終結果。


這是關於如何工作的快速教程;您應該查看Active Record Query Interface GuideEnumerable documentation

如果你有兩件事情(ab)來搭配,你可以這樣做:

q = Model.where('p like ?', "%#{a}%").where('p like ?', "%#{b}%") 

where方法返回一個支持所有常用的查詢方法的對象,所以你可以鏈接調用爲M.where(...).where(...)...爲需要;其他查詢方法(如orderlimit,...)返回相同類型的對象,所以你可以鏈的還有:

M.where(...).limit(11).where(...).order(...) 

你有東西像對數組,你想申請where添加到模型類中,然後將where應用於返回的內容,然後再次使用,直到用完陣列。事情看起來像一個反饋迴路趨向於(從「映射簡化」成名AKA reduce)呼籲inject

注入(初始){|備忘錄,obj | block}→obj

通過應用二進制操作(由命名方法或運算符的塊或符號指定)來組合enum的所有元素。

如果指定的塊,然後在枚舉每個元素的塊被傳遞的累加器值(備忘錄)和元素[...]的結果變成用於備忘錄新值。在迭代結束時,備忘錄的最終值是該方法的返回值。

所以inject取塊的輸出(這是在我們的例子的where的返回值),並饋送,作爲一個輸入到塊的下一次執行。如果你有一個數組,你inject

a = [1, 2, 3] 
r = a.inject(init) { |memo, n| memo.m(n) } 

那麼這就是與此相同:

r = init.m(1).m(2).m(3) 

或者,在僞代碼:

r = init 
for n in a 
    r = r.m(n) 
+0

哇!這樣可行!我剛剛接觸rails(和ruby),你介意給我一個關於這裏發生了什麼的簡短解釋嗎? – MGA

+0

@Mattieu:這有幫助嗎?解釋你一直使用的功能性東西可能很難,通常是「aha!」你得到它的那一刻,它在那之前就是魔術。 –

+1

@Mattieu,如果你不害怕添加寶石,請看一下squeel https://github.com/ernie/squeel。它有很棒的功能'like_all' /'like_any':'queries =%w [ruby rails] .map {| s |「%#{s}%」}; Product.where {title.like_all queries}'。 – jdoe

0

如果你使用的AR,這樣做Model.where(property: your_array),或Model.where("property in (?)", your_array)這樣一來,一切都消毒

+0

糾正我,如果我錯了,但不會做一個「=」?我需要做一個「like」 – MGA

+0

你是對的,我想我跳過了相似的部分,當我讀到 –

0

比方說,你的陣列是model_array,儘量陣列選擇:

model_array.select{|a|a.property=~/something/ and a.property=~/somethingelse/} 

當然,你可以使用任何正則表達式。