代码之家  ›  专栏  ›  技术社区  ›  learner2017

动态创建查询-Rails 5

  •  1
  • learner2017  · 技术社区  · 6 年前

    如果我手动编写查询,它将如下所示

    User.where("name LIKE(?) OR desc LIKE(?)",'abc','abc')
        .where("name LIKE(?) OR desc LIKE(?)",'123','123')
    

    但是,我需要动态生成该查询。 我得到的数据如下

    def generate_query(the_query)
    
       query,keywords = the_query
    
       # Here 
       # query = "name LIKE(?) OR desc LIKE(?)"
       # keywords = [['abc','abc'],['123','123']]
    
       keywords.each do |keyword|
           users = User.where(query,*keyword) <-- not sure how to dynamically add more 'where' conditions.    
        end
    
    end
    

    我正在使用Rails 5。希望这是清楚的。感谢您的帮助:)

    1 回复  |  直到 6 年前
        1
  •  2
  •   mu is too short    5 年前

    类似这样:

    q = User.where(a)
            .where(b)
            .where(c)
    

    相当于:

    q = User
    q = q.where(a)
    q = q.where(b)
    q = q.where(c)
    

    所以你可以写:

    users = User
    keywords.each do |keyword|
      users = users.where(query, *keyword)
    end
    

    但任何时候你看到这种反馈模式(即对操作的结果应用一个操作,或 f(f( ... f(x))) )你应该开始考虑 Enumerable#inject (又名 Enumerable#reduce ):

    users = keywords.inject(User) { |users, k| users.where(query, *k) }
    

    也就是说,你的 query 有两个占位符,但 keywords 只是一个平面数组,因此您在中没有足够的值:

    users.where(query, *k)
    

    替换占位符。我认为您最好在此处使用命名占位符:

    query    = 'name like :k or desc like :k'
    keywords = %w[abc 123]
    users    = keywords.inject(User) { |users, k| users.where(query, k: k) }
    

    您可能还希望为您的 LIKE 因此:

    query = "name like '%' || :k || '%' or desc like '%' || :k || '%'"
    users = keywords.inject(User) { |users, k| users.where(query, k: k) 
    

    哪里 || 是标准的SQL字符串连接运算符(AFAIK并非所有数据库都理解),并且 % 以相似的模式匹配任何字符序列。或者,您可以在Ruby中添加模式匹配,避免担心数据库处理字符串串联的不同方式:

    query = 'name like :k or desc like :k'
    users = keywords.inject(User) { |users, k| users.where(query, k: "%#{k}%")
    

    此外,这:

    User.where("name LIKE(?) OR desc LIKE(?)",'abc','abc')
        .where("name LIKE(?) OR desc LIKE(?)",'123','123')
    

    生成 WHERE 条款如下:

    where (name like 'abc' or desc like 'abc')
      and (name like '123' or desc like '123')
    

    所以你匹配了 全部的 关键字,而不是 任何 其中之一。这可能是你的意图,也可能不是。