如何显示pg-search multisearch结果的摘录

时间:2012-06-21 14:24:24

标签: ruby-on-rails pg-search

我在Heroku上的Rails应用程序中设置了pg_search:

@query = 'fast'
PgSearch.multisearch(@query) #=>
[#<PgSearch::Document searchable: ferrari, :content: 'this car is really fast'>,
 #<PgSearch::Document searchable: viper, :content: 'a very fast car'>]

我想在content的摘录中显示这些结果,以显示匹配发生的位置。当excerpt(content, @query)只有一个单词时,我可以致电@query以获得我想要的内容,但excerpt()仅处理完全匹配,因此如果:{/ p>

@query = 'car fast'
PgSearch.multisearch(@query) #=>
[#<PgSearch::Document searchable: ferrari, :content: 'this car is really fast'>,
 #<PgSearch::Document searchable: viper, :content: 'a very fast car'>]

然后excerpt(content, @query)为零,因为content中没有任何地方出现确切的短片'car fast'。

我认为excerpt(content, @query.split(' ').first)至少为多字查询显示某些内容,但仍然存在以下情况:

@query = 'car?'
@results = PgSearch.multisearch(@query) #=>
[#<PgSearch::Document searchable: ferrari, :content: 'this car is really fast'>,
 #<PgSearch::Document searchable: viper, :content: 'a very fast car'>]
excerpt(@results.first.content, @query) #=> nil

那么,当使用pg_search时,人们如何显示搜索结果的摘录?

4 个答案:

答案 0 :(得分:2)

我是pg_search的作者和维护者。

现在没有内置的方法可以在pg_search中获取结果摘录,但如果我或其他人有时间构建它,很容易就会出现。

PostgreSQL有一个函数ts_headline,您可以调用它将字符串摘录作为列返回。

可能会调用这样的东西(我还没有测试过):

PgSearch.multisearch(@query).select(["ts_headline(pg_search_documents.content, plainto_tsquery(?)) AS excerpt", @query])

然后,您的每个结果都应该有一个excerpt方法,可以返回您想要的内容。

顺便说一句,这是我最终想要在pg_search中自动生成的东西。我还没有时间深入研究它。

答案 1 :(得分:1)

FWIW-按照上面的nertzy示例,我能够使用以下内容:

PgSearch.multisearch(@query).select("ts_headline(pg_search_documents.content, plainto_tsquery('english', ''' ' || unaccent('#{@query}') || ' ''' || ':*')) AS excerpt")

我无法让plainto_tsquery(?)工作,因为它抛出了语法错误。我上面的解决方案只是做

的结果
PgSearch.multisearch(@query).select(["ts_headline(pg_search_documents.content, plainto_tsquery(?)) AS excerpt", @query]).to_sql

然后插入to_tsqueryplainto_tsquery调用的{{1}}个参数 - 我确信这不是完全合理的,但似乎有效。

答案 2 :(得分:0)

如果插入字符串,则会受到SQL注入攻击。

由于.select不接受像.where那样的参数化语句(Users.where("id = ?", params[:id])),因此您需要明确清理。

sanitized = ActionController::Base.helpers.sanitize(params[:q])
@results = PgSearch.multisearch(params[:q])
                  .select(["ts_headline(pg_search_documents.content, plainto_tsquery('english', ''' ' || '#{sanitized}' || ' ''' || ':*')) AS excerpt"])

答案 3 :(得分:0)

有一种更简单的方法,如果你不想通过SQL挖掘 - 你可以利用内置的pg_search gem功能以一种非常简单直接的方式显示摘录:

在您的控制器中:

@articles = Article.search(params[:search]).with_pg_search_highlight

在您看来:

= raw(article.pg_search_highlight)

应该这样做。