1

我遵循了PostgreSQL Railscast 中的全文搜索,但我得到了一些奇怪的行为。

例如,当我搜索“警察”时,我没有得到任何结果,但当我搜索“警察”时,我得到了。(警察存在于我正在搜索的内容中)。它也根本没有返回一些结果——但我知道这个词是存在的,无论这个词是大是小。

当我启动 rails dbconsole 时,它​​说我正在使用 psql (9.1.4),并且应用程序的其余部分似乎也正常运行。

我需要重建索引还是什么?

我正在使用 PG gem 和 postgres_ext gem,我没有使用 texticle 或 pg_search gem(因为我真的不需要添加的功能)。

我的代码与截屏视频相同:

def self.text_search(query)
  if query.present?
    rank = "ts_rank(to_tsvector(name), plainto_tsquery(#{sanitize(query)}))"
    where("to_tsvector('english', name) @@ :q 
           or to_tsvector('english', content) @@ :q", q: query).order("#{rank} desc")
  else
    scoped
  end
end

我已经创建了这样的索引:

class AddSearchIndexToArticles < ActiveRecord::Migration
  def up
    execute "create index articles_name on articles using gin(to_tsvector('english', name))"
    execute "create index articles_content on articles using gin(to_tsvector('english', content))"
  end
end

有趣的是,如果我在 where 调用中删除对 to_tsvector 的调用:

def self.text_search(query)
  if query.present?
    rank = "ts_rank(to_tsvector(name), plainto_tsquery(#{sanitize(query)}))"
    where("name @@ :q 
           or content @@ :q", q: query).order("#{rank} desc")
  else
    scoped
  end
end

...它按预期工作(除了因为索引似乎被忽略而非常慢)

有什么想法吗?

更新:

打开完整日志记录后,这里是正在运行的 sql:

LOG:  statement: SELECT 1
LOG:  statement: SELECT  "dogs".* FROM "dogs"  WHERE (to_tsvector('english', name) @@ 'wary' 
               or to_tsvector('english', other_names) @@ 'wary'
               or to_tsvector('english', origin) @@ 'wary'
               or to_tsvector('english', kusa) @@ 'wary') ORDER BY         ts_rank(to_tsvector(name), plainto_tsquery('wary'))
     desc LIMIT 10 OFFSET 0
LOG:  statement: SELECT 1
LOG:  statement: SELECT 1

我不是 sql 专家,但查询看起来没问题?

另外,我不确定它是否相关,但日志文件中也有很多:

FATAL:  lock file "postmaster.pid" already exists
HINT:  Is another postmaster (PID 821) running in data directory "/usr/local/var/postgres"?

我通过自制软件安装了 postgres,并且正在使用 9.1.4

4

1 回答 1

4

考虑一下警察这个词是如何被转换的to_tsvector

select to_tsvector('english','police');

结果是:

to_tsvector
-------------
 “警察”:1

如果我们直接将其与Police进行比较,则不会匹配:

select to_tsvector('english','police') @@ 'police' as match;

结果是:

匹配
----------
 F

(在这种情况下,f 是布尔值false)。

但是,如果针对 的结果进行比较plainto_tsquery,则它确实匹配:

select to_tsvector('english','police') @@ plainto_tsquery('english','police')  as match;

结果是:

匹配
--------
 吨

结论:不要将 tsvector 直接与单词匹配,将其与plainto_tsquery, 或的结果匹配to_tsquery


您可能还需要加强其他一些内容:当前,您的查询既包含显式传递给它的英语to_tsvector配置的调用,也包含没有此参数的调用(在子句中),在这种情况下,它默认为参数的当前值。如果并且当此参数与english不同时,可能会在某些表达式中产生意想不到的结果。最好始终传递此参数,或始终忽略它。后一种情况具有简洁的优点,并且避免了对特定语言进行硬编码。ORDER BYdefault_text_search_config

于 2012-08-19T10:21:14.260 回答