2

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

4

3 回答 3

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 也是一种选择,那么您只需要担心_and %

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 百分号”的混乱)放入实用程序方法中,以使您的代码更清洁。

如果您不关心大小写,则可以使用~*orilike进行不区分大小写的模式匹配。

于 2013-09-21T02:09:02.307 回答
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)
于 2013-09-21T11:19:31.917 回答
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)
于 2013-09-21T00:57:09.730 回答