在rails中按优先级排序的搜索结果

时间:2014-07-04 11:31:17

标签: postgresql sorting search ruby-on-rails-4

我正在搜索产品的标题和描述。它工作很酷,但我需要一个搜索喜欢得到一个结果优先。喜欢在结果中产品与标题匹配首先出现描述。 这是我的控制器代码:

def products
    scope = Product.joins(:vendor).enabled.includes(:vendor, :images)

    # Make sure to select only available vendors
    scope = scope.where("vendors.enabled = ?", true)

    # Filter by vendor
    if params[:vendor_id].present?
      scope = scope.where(vendor_id: params[:vendor_id])
    end

    if params[:search].present?
      scope = scope.filter(params[:search])
    end
    scope
  end

这是模特。 product.rb

def self.filter(search)
    where("title ILIKE '%#{search}%' OR description ILIKE '%#{search}%'")
  end

1 个答案:

答案 0 :(得分:1)

因此,结果将是您有一组Product个与其中一个字段中的搜索匹配的对象。

缺少的部分是,现在您需要对结果进行排序 - 您可以在查询中执行此操作,但这是相对艰苦的工作,我倾向于使用Ruby进行工作。

我首先会根据结果中搜索字词的出现次数生成结果分数,如下所示:

def score_result( result, search_term )
   score = result.title =~ search_term ? 5 : 0
   score+= result.text =~ search_term ? 1: 0
end

然后您可以将其作为搜索过滤器使用:

if params[:search].present?
  searchPattern = Regexp.new(params[:search])
  scope = scope.filter(params[:search]).sort_by { | res | score_result(res, searchPattern) }
end

这应该对术语在第一个中出现的结果进行排序,然后在出现在标题中的那些,然后出现在仅出现在文本中的那些结果。

有几点需要注意:

  1. 这是非常幼稚的解释 - 如果您的搜索字词为top hats and tails会发生什么 - 您是否只想匹配该确切的短语?你应该拆分它,然后为每个单词分配一个分数?如果您这样做,是否要返回标题或文本包含and作为搜索结果的结果?你怎么称重他们?如果一个单词匹配多次,那么该分数应该与每个匹配一次的不同单词一样高吗?
  2. 这是一个相当普遍的问题,在Ruby世界中,这意味着有人可能已经解决了它实际上可能有很多人已经解决了它。总是值得四处搜索,看看是否有任何方便的宝石,你可以放入你的捆绑包,这将允许你使用别人的代码来解决你的问题 - 在这种情况下像SearchLogic这样的东西看起来像虽然它可能有所帮助。