我会跳过 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
进行不区分大小写的模式匹配。