Rails:如何使用逗号分隔值并构建SQL查询?

时间:2013-09-20 23:47:42

标签: sql ruby-on-rails ruby postgresql

使用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的语法不太熟悉。

3 个答案:

答案 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)