使用 pg_textsearch 进行全文搜索

Cloud SQL for PostgreSQL 中的 pg_textsearch 扩展程序使用行业标准的 BM25(最佳匹配 25)得分算法提供全文搜索功能,可实现高度准确的相关性得分。该扩展程序是一个开源项目,可在 GitHub 上找到。

pg_textsearch 扩展程序需要 PostgreSQL 17 或更高版本。

由于 pg_textsearch 支持逆文档频率、词频饱和度和文档长度归一化,因此与 PostgreSQL 的内置 ts_rank 函数相比,它可以生成更相关的结果。此外,由于它直接在标准 PostgreSQL 存储页面上运行,因此您无需安装 Elasticsearch 等外部引擎,也不必担心双集群维护和数据同步问题。借助 pg_textsearch,您可以在不离开 PostgreSQL 生态系统的情况下,打造强大、可伸缩且高度相关的搜索体验。

Cloud SQL for PostgreSQL 中有多种文本搜索选项:

  • 完全匹配:使用标准 SQL 搜索时,您可以使用 LIKEILIKE 语句来扫描完全匹配的字符序列。例如,查询 ILIKE '%smart fitness watches%' 会找到以下实例:

    • “探索我们正在促销的全新智能健身手表。”
    • 智能健身手表是绝佳的礼物。”

    不过,它无法找到:

    • 跑者想要一款智能防水健身手表
    • “这款手表健身方面尤其智能。”
  • 全文搜索:使用 BM25 算法和 tsvector,全文搜索会将文本拆分为词根,忽略过滤字词,并对相关性进行评分。它了解语言规则(包括复数和语法),并会考虑字词频率。对 smart AND fitness AND watches 进行全文搜索会找到示例完全匹配查询会错过的实例,以及以下更复杂的实例:

    • 智能手表非常适合日常健身。”
    • “在健身方面,并非所有手表都如此智能。”

    不过,它无法找到:

    • “智能健康感知手表可以帮助你制定锻炼计划。”
    • “这款智能运动追踪手环非常划算。”
  • 语义搜索:语义搜索使用 AI 模型将文本转换为向量并衡量相似度距离。它能理解含义、意图、上下文、同义词和相关概念。如果使用语义搜索来搜索 smart fitness watches,则会找到其他搜索方法会遗漏的示例实例。语义搜索会理解“智能健康感知手表”与“智能健身手表”是相同的,并且“智能运动追踪手环”也可能相关。如果未充分优先考虑“手表”,则可能会错误地匹配计步器手环。

安装 pg_textsearch 扩展程序

请按以下步骤安装并启用 pg_textsearch

  1. 按照配置数据库标志中的说明,将 cloudsql.enable_pg_textsearch 标志设置为 on。这会将 pg_textsearch 添加到 shared_preload_libraries

  2. 安装 pg_textsearch 扩展程序

      CREATE EXTENSION pg_textsearch;
    
  3. 验证安装:

      SELECT extversion FROM pg_extension WHERE extname = 'pg_textsearch'
    

使用 pg_textsearch 进行搜索

假设以下示例表已填充数据:

CREATE TABLE documents (
    doc_id TEXT PRIMARY KEY,
    content TEXT,
    text_embedding vector(3072)
    GENERATED ALWAYS AS (embedding('gemini-embedding-001', content)) STORED 
  );

在使用全文搜索之前,请先创建 BM25 索引:

CREATE INDEX idx_docs_bm25
      ON documents
      USING bm25 (content)
      WITH (text_config = 'english');

然后,您可以发出如下所示的全文搜索查询:

SELECT doc_id, content, content <@> 'database system'
      AS score FROM documents
      ORDER BY content <@> 'database system'
      ASC LIMIT 5;

使用 pg_textsearchvector 执行混合搜索

您可以将 pg_textsearchvector 语义搜索扩展程序搭配使用,以执行混合搜索。按如下方式安装 vector 语义搜索扩展程序:

CREATE EXTENSION IF NOT EXISTS vector CASCADE;

发出如下混合语义搜索和全文搜索查询:

WITH
  -- Semantic search results
  vector_search AS (
    SELECT doc_id,
      RANK () OVER (ORDER BY text_embedding <=>
                             google_ml.embedding('gemini-embedding-001',
                                                 'database')::VECTOR ) AS rank
      FROM documents
      ORDER BY text_embedding <=> google_ml.embedding('gemini-embedding-001',
                                                      'database')::VECTOR
    LIMIT 10
  ),
  -- Full text search results
  text_search AS (
    SELECT doc_id,
      RANK () OVER (ORDER BY content <@> 'database' ASC) AS rank
    FROM documents
    ORDER BY content <@> 'database' ASC
    LIMIT 10
  )
  -- RRF combining both semantic and full text search results
  SELECT
    COALESCE(vector_search.doc_id, text_search.doc_id) AS id,
    COALESCE(1.0 / (60 + vector_search.rank), 0.0) +
    COALESCE(1.0 / (60 + text_search.rank), 0.0) AS rrf_score
  FROM vector_search
    FULL OUTER JOIN text_search ON vector_search.doc_id = text_search.doc_id
  ORDER BY rrf_score DESC
  LIMIT 5;

用于配置 pg_textsearch 扩展程序的标志

使用以下标志配置 pg_textsearch 全文搜索: