【问题标题】:Postgres: Add full-text search on existing varchar column?Postgres:在现有的 varchar 列上添加全文搜索?
【发布时间】:2015-04-16 19:03:50
【问题描述】:

我有一个现有的 Postgres 9.3 数据库,其中包含一个带有 varchar 列的表。

        Table "public.frontend_chemical"
  Column   |          Type          | Modifiers
-----------+------------------------+-----------
 bnf_code  | character varying(9)   | not null
 chem_name | character varying(200) | not null

我想在chem_name 列上运行全文搜索。

我一直在阅读this article,建议步骤如下:

  1. 添加新的tsvector 列:ALTER TABLE frontend_chemical ADD COLUMN fts_document tsvector;
  2. 创建一个函数以将chem_name 列映射到文档,并创建一个触发器以使其保持更新。
  3. 在列上创建 GIN 索引:CREATE INDEX chem_fts_index ON frontend_chemical USING gin(fts_document);

然后我应该能够运行全文搜索查询,例如:SELECT COUNT(*) FROM frontend_chemical WHERE fts_document @@ 'statin';

首先,一般流程是否正确?

其次,如何将chem_name 列中的所有现有条目映射到fts_document 列?文章中的示例似乎只在更新chem_name 列时更新document 列,而我现有的数据库很大。

【问题讨论】:

    标签: postgresql


    【解决方案1】:

    这个过程是正确的,但在你的情况下可能有点矫枉过正。

    由于需要对单个列进行全文搜索,您可以取消专用的tsvector 列,只创建 GIN 索引:

    CREATE INDEX chem_fts_index ON frontend_chemical
        USING gin(to_tsvector('simple',chem_name));
    

    如果需要语言规则,您可以指定english 或其他可用的configuration,而不是simple

    然后您将在搜索时从索引中受益:

    select columns from frontend_chemical where
       to_tsvector('simple', chem_name) @@ to_tsquery('simple','expression to search');
    

    关键是tsvector表达式与GIN索引中的完全一样。

    这具有不需要触发器的优点,节省了值已经在索引中的专用列的空间,并且不需要初始化该列(您的第二个问题)。


    如果您仍然想要该列,最初应该使用这种形式的更新查询填充它:

    UPDATE frontend_chemical SET fts_document = to_tsvector('simple', chem_name);
    

    (再次假设 simple 作为文本搜索配置)


    编辑以下 cmets:

    to_tsquery() 只有一个参数使用默认文本配置(否则配置名称应作为第一个参数传递)。 如果此默认值与to_tsvector 中使用的不匹配,那就有问题了。可以通过多种方式更改默认值:

    • 在会话期间(非持久性)

          SET default_text_search_config to 'simple';
      
    • 用于数据库(持久化)

          ALTER DATABASE nameofdb SET default_text_search_config to 'simple';
      
    • 否则,请始终为 to_tsquery 使用双参数形式,并将显式文本配置名称作为第一个参数(我已将上面的示例更改为使用该形式)。

    要使用 Ro 搜索您想要的前缀,您可以使用以下条件:

    to_tsvector('simple', chem_name) @@ to_tsquery('simple', 'Ro:*')
    

    更多信息请参阅手册中的Controlling Text Search

    【讨论】:

    • 唯一的问题是查询似乎没有做任何事情:select * from frontend_chemical where to_tsvector('simple', chem_name) @@ to_tsquery('Ro') 不产生任何结果,而select * from frontend_chemical where chem_name like 'Ro%' 产生大量结果。我是否误解了如何进行查询?
    • A \d 表明索引肯定存在于表中:"chem_fts_index" gin (to_tsvector('simple'::regconfig, chem_name::text)),我也运行了 ANALYZE
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-06
    • 2018-02-03
    • 2012-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多