1

我正在使用 Rails 3.2.2 和 MySQL。我正在通过用户名(例如,、、、)搜索John数据库AnthonyMark列:

# 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).

如何正确搜索多个名称?

4

2 回答 2

1

I totally think you should do one of the following,

Mysql full text search:

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

SphinxSearch:

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

  • I recommend sphinxsearch since I use it with various cool features built in with it.
  • Support for sphinx is amazing too!
于 2012-05-21T09:08:34.793 回答
1

使用 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”。所以我有点开心。

于 2012-05-21T10:24:36.683 回答