【问题标题】:How to search for multiple strings in a database table column?如何在数据库表列中搜索多个字符串?
【发布时间】:2012-05-21 05:55:42
【问题描述】:

我正在使用 Rails 3.2.2 和 MySQL。我正在按用户名(例如,JohnAnthonyMark)搜索数据库表列:

# User controller
User.search_by_name(params[:search]).order(:name)

# User model
def self.search_by_name(search)
  if search
    where('users.name LIKE ?', "%#{search}%")
  else
    scoped
  end
end

但是,由于名称可以由两个或多个字符串组成(例如,John HenryHenry JohnAnthony MariaMaria AnthonyMark AlfredAlfred Mark),我会喜欢在params[:search] 提供多个名称时也搜索用户。我尝试使用

def self.search_by_name(search)
  if search
    search.split(' ').each do |string|
      where('users.name LIKE ?', "%#{string}%")
    end
  else
    scoped
  end
end

但我收到以下错误(例如,假设我正在搜索 John Henry):

NoMethodError (undefined method `order' for ["John", "Henry"]:Array).

如何正确搜索多个名称?

【问题讨论】:

  • 如果您在数据库中有“John Henry”并且有人搜索“John”,它应该匹配吗?如果名字是“Mark Anthony”并且有人搜索“Maria Anthony”怎么办?
  • @mu 太短 - a) 如果你的数据库中有“John Henry”并且有人搜索“John”,它应该匹配吗? i> 是的,应该。 b) 如果名字是“Mark Anthony”并且有人搜索“Maria Anthony”怎么办?在这种情况下它应该返回匹配“Maria”的记录或 “Anthony”(因此,在您的示例中,它应该包括“Mark Anthony”)但记录应该ordered考虑到匹配的“level”(也就是说,记录应该按照那些将“更好”与“Maria Anthony”匹配——我不知道是否可以直接使用 MySQL 查询)。
  • 看看stackoverflow.com/a/10551561/1322562。示例中的最后一个功能 -- like_any 必须是您的情况。您可以使用类似:names=params[:search].split; @users=User.where{name.like_any(names)}.

标签: mysql sql ruby-on-rails ruby ruby-on-rails-3


【解决方案1】:

我完全认为您应该执行以下操作之一,

Mysql全文搜索:

http://devzone.zend.com/26/using-mysql-full-text-searching/

狮身人面像搜索:

http://www.ibm.com/developerworks/library/os-php-sphinxsearch/

  • 我推荐 sphinxsearch,因为我将它与各种很酷的功能一起使用 内置它。
  • 对 sphinx 的支持也很棒!

【讨论】:

    【解决方案2】:

    使用 squeel 宝石。

    def self.search_by_name(search)
      if search
        where(name.like_any search.split)
      else
        scoped
      end
    end
    

    请注意,这不会按匹配级别排序。为此,您需要一个搜索引擎实现,例如 sphinx、solr、xapian 的 gems

    还请注意,您最初对每个条件的使用是不正确的,因为您的意思是“或”条件。如果您不介意发出与搜索词一样多的数据库查询,您甚至可以伪造匹配级别的排序。

    def self.search_by_name(search)
      if search
        results = search.split.map do |string|
          where('users.name LIKE ?', "%#{string}%").all
        end.flatten
        ids = results.map(&:id)
        # desc order by count of matches
        ordered_results = results.uniq.order { |result| -ids.count(result.id) }
      else
        scoped.all
      end
    end
    

    这不是一个可以进一步限定范围的 Arel 关系,而是一个普通数组。 请注意“全部”调用,因此甚至不要在大数据库上尝试此操作。 另请注意,如果搜索是 'a b' 等,这不会在 'b a' 之上排序 'a b'。 所以我只是玩得开心。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多