2

我在 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)以获得我想要的确切内容,但只处理完全匹配,所以如果:@queryexcerpt()

@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'>]

thenexcerpt(content, @query)为 nil,因为在任何地方都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

4 回答 4

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 中自动实现的东西。我只是还没有时间深入研究它。

于 2012-10-13T18:42:12.193 回答
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调用的参数——我敢肯定这并不完全正确,但似乎有效。

于 2013-01-15T22:47:02.913 回答
0

如果对字符串进行插值,就会受到 sql 注入攻击。

由于.select不会接受像.wheredos ( 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"])
于 2015-08-19T22:19:51.003 回答
0

有一种更简单的方法,如果您不想深入研究 SQL - 您可以利用内置的 pg_search gem 功能以非常简单直接的方式显示摘录:

在您的控制器中:

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

在您看来:

= raw(article.pg_search_highlight)

那应该这样做。

于 2016-07-15T12:51:01.757 回答