从数组构建LIKE子句

时间:2012-12-31 20:22:39

标签: ruby-on-rails ruby-on-rails-3 activerecord

我正在尝试一些概念(实际上通过构建1978年数据库WHRSIT的RoR版本来玩和学习?)。

它基本上是一个has_many:通过结构与主题 - >标签< - 价值。我试图通过使用查询文本字段来输入命令来复制一些命令行结构。基本上是这样的事情:What's steve's phone

无论如何,使用该界面,大多数搜索都使用ILIKE。我想通过允许OR条件使用某种形式的数组来增强它。像What's steve's [son,daugher]这样的东西。我通过直接创建ILIKE子句来实现它,但不是使用字符串替换。

def bracket_to_ilike(arrel,name,bracket)
  bracket_array = bracket.match(/\[([^\]]+)\]/)[1].split(',')
  like_clause = bracket_array.map {|i| "#{name} ILiKE '#{i}' "}.join(" OR ")
  arrel.where(like_clause)
 end  

bracket_to_ilike(tags,'tags.name','[son,daughter]')生成类似条款tags.name ILiKE 'son' OR tags.name ILiKE 'daughter'

它得到了关系,但是关于使用("tags.name ILiKE ? OR tags.name ? ",v1,v2,vN..)形式的所有讨论,我虽然问我是否有任何想法如何做到这一点。

动态创建变量是可以从我搜索过的,但不是赞成的。我只是想知道是否有人尝试创建一个方法,可以添加一个具有可变数字参数的where子句。我尝试将where子句发送给关系,但它并不是那样。

史蒂夫

2 个答案:

答案 0 :(得分:0)

您的代码需要注意的事情......

  • 当bracket_array的某个元素包含单引号时会发生什么?
  • 如果我更进一步,并设置一个元素来说"&#39 ;;放表......"?

我第一次尝试重构你的代码就是看看Arel是否可以做到这一点。或者是Sequeel,或者他们称之为" metawhere"宝石这几天。我的第二次尝试将是这样的:

arrel.where( [ bracket_array.size.times.map{"#{name} ILIKE ?"}.join(' OR '), *bracket_array ])

我没有测试它,但想法是使用bracket_array的大小生成一串OR条件,然后使用splat运算符传入所有值。

答案 1 :(得分:0)

感谢Phillip指出我正确的方向。

  • 我不知道你可以将数组传递给where子句 - 这会打开一些选项
  • 我曾经使用过splat运算符几次,但它并没有让我觉得它实际上创建了一个对象(变量)

[儿子,女儿]的东西只是一个控制台练习,看看我能做什么,但不知道我将用它做什么。我最终获得了模型关联并从图片中创建了数组并实现了OR搜索。

def array_to_ilike(col_name,keys)
  ilike = [keys.map {|i| "#{col_name} ILiKE ? "}.join(" OR "), *keys ]
  #ilike = [keys.size.times.map{"#{col_name} ILIKE ?"}.join(' OR '), *keys ]
  #both work, guess its just what you are use to.
end  

然后我在主题,标签,值搜索中允许管道(|)字符,所以WHATSIT样式问题

  • What's Steve's Phone Home|Work =>显示家庭和工作电话
  • steve phone home|work这些东西只是为了展示
  • steve son|daughter =>显示孩子
  • phone james%|lori% =>显示任何名字以james或lori开头的人的电话号码
  • james%|lori% =>转储任何名字以james或lori开头的人的所有信息

然后查询解析命令,如果遇到|在任何一个词中,它都会做如下事情:

t_ilike = array_to_ilike('tags.name',name.split("|"))
# or I actually stored it off on the inital parse
t_ilike = @tuple[:tag][:ilike] ||= ['tags.name ilike ?',tag]

同样,这只是一个创建非CRUD类来处理解析和搜索的学习练习。

史蒂夫