Ruby – Rails – SQL查询 – 在搜索词中重新排序单词

我正在开发一个带有搜索function的项目,其设置如下:

if params[:search_term].present? && params[:search_term].length > 1 @candidates = @candidates.where("title like ?","%#{params[:search_term]}%") end 

客户要求我“放松”搜索 – 特别是单词顺序。 目前,如果有候选人的White bar stool的标题和一个搜索White stool bar ,它没有返回任何结果。

有没有办法让我执行一个忽略单词顺序的查询? 或者,对于我来说,使用不同的单词顺序制作新的搜索词params,进行多次搜索并合并结果会更好吗?

你可以考虑使用ArelArel是rails / activerecord的底层查询汇编程序(因此没有新的依赖项),并且在构建复杂查询时非常有用,因为它提供的深度远远高于高级ActiveRecord::QueryMethods

Arel提供了大量的预测匹配器,包括matches_anymatches_all 。 这些方法使用一个String of String并使用Like将它们分成单独的搜索条件。

例如,要搜索包含搜索到的任何单词的所有候选项,您可以使用:

 class Candidate < ActiveRecord::Base def self.search_for(term) candidates = Candidate.arel_table where( candidates[:title].lower.matches_any( term.split.map { |t| "%#{t.downcase}%" } ) ) end end 

search_for的最终结果(给定搜索词“白凳”)是:

 SELECT [candidates].* FROM [candidates] WHERE ( LOWER([candidates].[title]) LIKE '%white%' OR LOWER([candidates].[title]) LIKE '%stool%' OR LOWER([candidates].[title]) LIKE '%bar%') 

这似乎是你在寻找什么。 如果它必须匹配所有条款,您可以改为使用matches_all ,这将导致:

 SELECT [candidates].* FROM [candidates] WHERE ( LOWER([candidates].[title]) LIKE '%white%' AND LOWER([candidates].[title]) LIKE '%stool%' AND LOWER([candidates].[title]) LIKE '%bar%') 

请参阅此处了解所有可用的Arel预测。

这增加了基本转义的好处,以避免像SQL注入这样的事情。

您可以使用MySQL RLIKE运算符来匹配您可以使用句子创建的特定模式。

 sentence = 'White stoll bar' @candidates = @candidates.where('title RLIKE ?', "(#{sentence.tr(' ', '|')})")