如果我手动编写查询,它会像
User.where("name LIKE(?) OR desc LIKE(?)",'abc','abc')
.where("name LIKE(?) OR desc LIKE(?)",'123','123')
但是,我需要动态生成该查询。 我正在获得这样的数据
def generate_query(the_query)
query,keywords = the_query
# Here
# query = "name LIKE(?) OR desc LIKE(?)"
# keywords = [['abc','abc'],['123','123']]
keywords.each do |keyword|
users = User.where(query,*keyword) <-- not sure how to dynamically add more 'where' conditions.
end
end
我正在使用 Rails 5。希望清楚。任何帮助表示赞赏:)
像这样:
q = User.where(a)
.where(b)
.where(c)
相当于:
q = User
q = q.where(a)
q = q.where(b)
q = q.where(c)
所以你可以写:
users = User
keywords.each do |keyword|
users = users.where(query, *keyword)
end
但是,每当您看到这种反馈模式(即将操作应用于操作的结果或f(f( ... f(x)))
)时,您都应该开始考虑Enumerable#inject
(AKAEnumerable#reduce
):
users = keywords.inject(User) { |users, k| users.where(query, *k) }
也就是说,您的query
有两个占位符,但keywords
只是一个平面数组,因此您将没有足够的值:
users.where(query, *k)
以替换占位符。我认为您最好在这里使用命名占位符:
query = 'name like :k or desc like :k'
keywords = %w[abc 123]
users = keywords.inject(User) { |users, k| users.where(query, k: k) }
您可能还希望为您的LIKE
包含一些模式匹配,以便:
query = "name like '%' || :k || '%' or desc like '%' || :k || '%'"
users = keywords.inject(User) { |users, k| users.where(query, k: k)
其中||
是标准的 SQL 字符串串联运算符(并非所有数据库都能理解 AFAIK),LIKE 模式中的%
匹配任何字符序列。或者,您可以在 Ruby 中添加模式匹配,而不必担心数据库处理字符串连接的不同方式:
query = 'name like :k or desc like :k'
users = keywords.inject(User) { |users, k| users.where(query, k: "%#{k}%")
此外,这:
User.where("name LIKE(?) OR desc LIKE(?)",'abc','abc')
.where("name LIKE(?) OR desc LIKE(?)",'123','123')
生成一个WHERE
子句,如下所示:
where (name like 'abc' or desc like 'abc')
and (name like '123' or desc like '123')
因此,您匹配的是所有关键字,而不是任何一个关键字。这可能是也可能不是您的意图。