【问题标题】:Ruby on Rails - search in database based on a queryRuby on Rails - 基于查询在数据库中搜索
【发布时间】:2012-12-03 14:26:28
【问题描述】:

我有一个简单的表单,我在其中设置了一个我想浏览的查询,例如 panasonic viera。 这是关于我如何在数据库中搜索该术语的:

Product.where("name ilike ?", "%#{params[:q]}%").order('price')

查询看起来像 %panasonic viera%,但我需要这样搜索查询:%panasonic%viera% - 我需要查找所有产品, panasonicviera 在标题中的哪个位置...但是如何进行此查询?

【问题讨论】:

  • 名字在哪里?或名字喜欢? (带多个参数)
  • 您的问题不清楚。您要搜索短语“panasonic viera”(这两个词都按此顺序出现),还是要搜索“panasonic”或“vieara”?
  • "%#{params[:q].gsub(' ', '%')}%"

标签: sql ruby-on-rails ruby activerecord sql-like


【解决方案1】:

一种解决方案是将您的查询分解为单独的术语,并构建一组由OR 连接的数据库查询。

terms = params[:q].split
query = terms.map { |term| "name like '%#{term}%'" }.join(" OR ")
Product.where(query).order('price')

【讨论】:

  • 谢谢你的回答。但说实话,我有点迷茫,因为:如果我有这个产品:KV VAIO E14A1S1EB 并且如果在params[:q]中是sony vaio,我希望应该找到该产品,但事实并非如此。但怎么可能呢?
  • 我的猜测是这与区分大小写有关 - 尝试将搜索字符串向上转换,看看是否有帮助?
  • 我已经实现了相同的,很抱歉它花费了太多时间来获取结果。我的数据库有超过 100,000 条记录。有没有有效的方法?
【解决方案2】:

如果您使用的是 PostgreSQL,则可以使用 pg_search gem。支持全文搜索,选项any_word:

Setting this attribute to true will perform a search which will return all models containing any word in the search terms.

来自pg_search的示例:

class Number < ActiveRecord::Base
  include PgSearch
  pg_search_scope :search_any_word,
                  :against => :text,
                  :using => {
                    :tsearch => {:any_word => true}
                  }

  pg_search_scope :search_all_words,
                  :against => :text
end

one = Number.create! :text => 'one'
two = Number.create! :text => 'two'
three = Number.create! :text => 'three'

Number.search_any_word('one two three') # => [one, two, three]
Number.search_all_words('one two three') # => []

【讨论】:

    【解决方案3】:

    通过ARel怎么样

    def self.search(query)
      words      = query.split(/\s+/)
      table      = self.arel_table
      predicates = []
    
      words.each do |word|
        predicates << table[:name].matches("%#{word}%")
      end
    
      if predicates.size > 1
        first = predicates.shift
        conditions = Arel::Nodes::Grouping.new(predicates.inject(first) {|memo, expr| Arel::Nodes::Or.new(memo, expr)})
      else
        conditions = predicates.first
      end
    
      where(conditions).to_a
    end
    

    【讨论】:

      【解决方案4】:

      这不起作用?

       WHERE name LIKE "panasonic" OR name LIKE "viera"
      

      【讨论】:

      • 搜索查询来自用户输入,因此 OP 需要一个可以动态构建数据库查询的解决方案。
      猜你喜欢
      • 1970-01-01
      • 2016-04-25
      • 2017-03-24
      • 1970-01-01
      • 1970-01-01
      • 2017-06-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-05
      相关资源
      最近更新 更多