【问题标题】:What is the best way to search for an exact match using Postgres full-text search?使用 Postgres 全文搜索搜索完全匹配的最佳方法是什么?
【发布时间】:2016-08-02 01:13:26
【问题描述】:

我有一个包含大约 150 万条记录的 Postgres 数据库。在我的 Ruby on Rails 应用程序中,我需要搜索 statement_text 字段(可以包含 1 到数百个单词)。

我的问题:我知道我可以使用pgSearch gem 来创建像search_all_wordssearch_any_words 这样的范围,但我不确定确保只有完全匹配的记录的最有效方法是什么 在结果集中返回。

也就是说,如果我搜索“教皇弗朗西斯”,我希望它只找到连续且顺序相同的这两个词(而不是说,“教皇名叫弗朗西斯”)。

到目前为止,我刚刚将 GIN 索引与 ILIKE 结合起来进行精确匹配搜索。但是考虑到 GIN 索引在每条记录中基本上都由storing the exact position of a word 起作用,难道不应该有更有效的(非ILIKE)方法来确保搜索词与字段完全匹配吗?

【问题讨论】:

    标签: ruby-on-rails postgresql full-text-search text-normalization


    【解决方案1】:

    一般来说,全文需要根据所使用的语言词典进行词干提取,因此使用全文搜索可以使用 ts_rank() 函数而不使用 词干'simple' 词典来确定您正在搜索的短语的相关性。

    WITH t(v) AS ( VALUES
      ('Test sentence with Pope Francis'),
      ('Test Francis sentence with Pope '),
      ('The pope is named Francis')
    )
    SELECT v,ts_rank(tsv,q) as rank
    FROM t,
        to_tsvector('simple',v) as tsv,
        plainto_tsquery('simple','Pope Francis') AS q;
    

    结果:

                    v                 |   rank    
    ----------------------------------+-----------
     Test sentence with Pope Francis  | 0.0991032
     Test Francis sentence with Pope  | 0.0973585
     The pope is named Francis        | 0.0973585
    (3 rows)
    

    没有全文搜索,您可以使用pg_trgm 扩展名实现更快的ILIKE 模式匹配。例如here

    【讨论】:

    • 谢谢,德米特里!我正在使用全文搜索,所以我可以使用 ts_rank。但是,问题在于——取决于字段的字数——没有特定的截止点可以确保单词相邻且顺序正确,而无需使用 ILIKE。我理解正确吗?
    • 不,没有基于长度的截断。如果短语匹配,它仍然会有更高的排名。您可以省略 ts_rank 的归一化因子 - 它应该可以正常工作。
    猜你喜欢
    • 2019-09-22
    • 2011-12-19
    • 1970-01-01
    • 1970-01-01
    • 2022-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多