使用Rails 3 Active Record模型(postgres db)我想用这样的用户搜索输入:
"some string, some other string, final string"
从那里我想在逗号上拆分字符串并构建一个看起来像这样的
的SQL查询SELECT * FROM items WHERE item_name SIMILAR TO '%(some string)%' OR item_name SIMILAR TO '%(some other string)%' OR item_name SIMILAR TO '%(final string)%'
我很难想出一种构建此查询的方法,因为我对Ruby的语法不太熟悉。
答案 0 :(得分:3)
我会跳过SIMILAR TO并直接转到POSIX regexes,我很确定SIMILAR TO会在内部翻译成正则表达式,所以为什么要这么麻烦?此外,~
将允许您使用ANY
生成一个可读的表达式。你可以这样做:
str = 'some string, some other string, final string'
items = Item.where('item_name ~ any(array[?])', str.split(/\s*,\s*/))
最终会像这样运行SQL:
select "items".* from "items" where item_name ~ any(array['some string', 'some other string', 'final string'])
这将产生与您的SIMILAR TO版本相同的结果,而不会发生一堆字符串争用。
如果您遇到可以包含正则表达式元字符的CSV字符串,那么您可能希望在混合中抛出一些转义符。反斜杠任何不是字母数字的东西应该足够安全:
str = 'some string, some other string, final string'
pats = str.split(/\s*,\s*/)
.map { |s| s.gsub(/\p{^Alnum}/) { '\\' + $& } }
items = Item.where('item_name ~ any(array[?])', pats)
切换到LIKE也是一种选择,那么您只需要担心_
和%
:
str = 'some string, some other string, final string'
pats = str.split(/\s*,\s*/)
.map { |s| s.gsub(/[_%]/, '%' => '\\%', '_' => '\\_') }
.map { |s| '%' + s + '%' }
items = Item.where('item_name like any(array[?])', pats)
在现实生活中,你会将逃避的混乱(以及“添加LIKE百分号”混乱)打入实用程序方法,以使代码更清晰。
如果您不关心案例,那么您可以使用~*
或ilike
进行不区分大小写的模式匹配。
答案 1 :(得分:3)
试试这种方式,
string = 'some string, some other string, final string'
patterns = search_string.split(", ").map{|str| "%#{str}%" }
items = Item.where('item_name like any(array[?])', patterns)
答案 2 :(得分:1)
这应该有用。
search_string = "some string, some other string, final string"
strings = search_string.split(", ").map{|s| '%' + s + '%'}
instructions = ''
strings.each do |string|
instructions << ' OR ' unless instructions == ''
instructions << 'item_name like ?'
end
DatabaseTable.where(instructions, *strings)