全部產品
Search
文件中心

AnalyticDB:BM25高效能全文檢索索引

更新時間:Jan 22, 2025

本文介紹pgsearch外掛程式的功能、安裝卸載、使用方法等,為您在實現強大的全文檢索索引方面提供參考。

功能簡介

pgsearch外掛程式實現了全新的BM25(Best Matching 25)索引,該索引基於高效能全文檢索索引引擎Tantivy構建。BM25是許多現代搜尋引擎(如 Elasticsearch)的優先選擇。它通過考慮一個詞項在記錄行中出現的頻率和該詞項在記錄行中的獨特性來對行進行排名。當您在記錄行中檢索關鍵詞或短語時,BM25十分有用。BM25索引能夠在AnalyticDB for PostgreSQL的表中進行全文檢索索引並使用BM25演算法進行相關性得分,從而匹配更準確的檢索結果。

安裝與卸載

pgsearch暫不支援白屏化安裝,如有需要請提交工單。聯絡工作人員協助安裝(需要重啟執行個體)。如有卸載外掛程式需求,也請提交工單聯絡工作人員協助卸載。

測試表

為方便測試,本文提供了一個範例表,範例表中預先插入了幾十條資料。執行pgsearch.create_test_table()會自動建立該範例表。

CALL pgsearch.create_test_table(table_name => 'mock_items', schema_name => 'public');

表結構如下所示

CREATE TABLE mock_items (
 description TEXT,
 rating INTEGER CHECK (
 rating BETWEEN 1
 AND 5
 ),
 category VARCHAR(255),
 in_stock BOOLEAN,
 metadata JSONB,
 created_at TIMESTAMP,
 last_updated_date DATE,
 latest_available_time TIME
);

索引管理

重要

建立索引和刪除索引均不支援復原。

建立索引

您可以使用pgsearch.create_bm25()函數建立BM25索引。該函數支援在多個欄位上建立索引,並為每個欄位指定相關的索引配置。建立多個索引會消耗過多的資源,從而影響使用體驗。因此建議一張表只建立一個BM25索引。

文法

CALL pgsearch.create_bm25(
  index_name => '<index_name>',
  table_name => '<table_name>',
  schema_name => '<schem_name>'
  text_fields => '<text_fields>|pgsearch.field()',
  numeric_fields => '<numeric_fields>|pgsearch.field()',
  boolean_fields => '<boolean_fields>|pgsearch.field()',
  json_fields => '<json_fields>|pgsearch.field()',
  datetime_fields => '<datetime_fields>|pgsearch.field()'
)

參數說明

參數

是否必填

支援的欄位類型

說明

index_name

String

索引名稱。

table_name

String

需要建立索引的表的名稱。

schema_name

String

表所在的Schema,預設為當前所在的Schema。

text_fields

至少設定一個。

  • VARCHAR

  • VARCHAR[]

  • TEXT

  • TEXT[]

定義哪些文字欄位被索引及這些欄位的索引方式。可以通過JSON5格式的字串或pgsearch.field()函數對每個欄位做索引配置。

  • 使用JSON5格式的字串配置。

    其結構為索引值對。其中鍵對應資料庫表中的欄位名稱,值則是一個設定物件。支援的配置如下。

    • fast:預設值為false。該欄位可以被迅速隨機訪問,也適用於加速得分和過濾。

    • fieldnorms:預設值為true。儲存文字欄位長度的資訊。必須為true才能計算BM25得分。

    • tokenizer:一個JSON5字串,指定分詞器及其配置選項。分詞器相關配置請參見分詞器

    • record:預設值為position。描述索引中包含的資訊。record相關配置請參見Record

  • 使用pgsearch.field()函數配置。

    pgsearch.field()函數用於產生指定欄位的配置串,多個欄位的配置可以通過多個pgsearch.field()產生,且它們之間應使用“||”符號進行串連。

    文法

    pgsearch.field(<name>, <fast>, <fieldnorms>, <record>, <expand_dots>, <tokenizer>)

    參數說明

    • name:文本類型,需要建立索引的列的名稱。

    • 關於fastfieldnormsrecordexpand_dotstokenizer參數詳情,請參見本表格的內容。

重要

僅v7.2.1.0及以上的核心版本支援pgsearch.field()函數。且v7.2.1.0及以上的核心版本必須使用pgsearch.field()函數建立索引。否則jieba分詞器的自訂分詞詞典和停用詞詞典將無法生效。

numeric_fields

  • INT2

  • INT2[]

  • INT4

  • INT4[]

  • INT8

  • INT8[]

  • OID

  • OID[]

  • XID

  • XID[]

  • FLOAT4

  • FLOAT4[]

  • FLOAT8

  • FLOAT8[]

  • NUMERIC

  • NUMERIC[]

定義哪些數值欄位被索引以及這些欄位的索引方式。可以通過JSON5格式的字串或pgsearch.field()函數對每個欄位做索引配置。

  • 使用JSON5格式的字串配置。

    其結構為索引值對。其中鍵對應資料庫表中的欄位名稱,值則是一個設定物件。支援的配置如下。

    fast:預設值為true。該欄位可以被迅速隨機訪問,也適用於加速得分和過濾。

  • 使用pgsearch.field()函數配置。

    pgsearch.field()函數用於產生指定欄位的配置串,多個欄位的配置可以通過多個pgsearch.field()產生,且它們之間應使用“||”符號進行串連。更多詳情請參見本表格的內容。

boolean_fields

  • BOOLEAN

  • BOOLEAN[]

定義哪些布爾欄位被索引以及這些欄位的索引方式。

  • 使用<boolean_fields>配置。

    支援的配置如下。

    fast:預設值為true。該欄位可以被迅速隨機訪問,也適用於加速得分和過濾。

  • 使用pgsearch.field()函數配置。

    pgsearch.field()函數用於產生指定欄位的配置串,多個欄位的配置可以通過多個pgsearch.field()產生,且它們之間應使用“||”符號進行串連。更多詳情請參見本表格的內容。

json_fields

  • JSON

  • JSONB

定義哪些JSON欄位被索引以及這些欄位的索引方式。

  • 使用JSON5格式的字串配置。

    其結構為索引值對。其中鍵對應資料庫表中的欄位名稱,值則是一個設定物件。一旦索引建立,就可以在JSON值內的嵌套文字欄位上執行檢索。支援的配置如下。

    • fast:預設值為false。該欄位可以被迅速隨機訪問,也適用於加速得分和過濾。

    • expand_dots:預設值為true。如果為true,則JSON鍵將通過.被展平。例如,當expand_dots為true,則{"metadata.color": "red"}將匹配到{"metadata": {"color": "red"}}。

    • tokenizer:en_stem,指定分詞器及其配置選項。分詞器相關配置請參見分詞器

    • record:預設值為position。描述索引中包含的資訊。record相關配置請參見Record

  • 使用pgsearch.field()函數配置

    pgsearch.field()函數用於產生指定欄位的配置串,多個欄位的配置可以通過多個pgsearch.field()產生,且它們之間應使用“||”符號進行串連。更多詳情請參見本表格的內容。

datetime_fields

  • DATE

  • DATE[]

  • TIMESTAMP

  • TIMESTAMP[]

  • TIMESTAMPTZ

  • TIMESTAMPTZ[]

  • TIME

  • TIME[]

  • TIMETZ

  • TIMETZ[]

定義哪些日期時間欄位被索引以及這些欄位的索引方式。如果未指定,檢索詞將使用UTC時區,並且採用RFC3339格式。支援的配置如下。

  • 使用<datetime_fields>配置

    支援的配置如下。

    fast:預設值為true。該欄位可以被迅速隨機訪問,也適用於加速得分和過濾。

  • 使用pgsearch.field()函數配置

    pgsearch.field()函數用於產生指定欄位的配置串,多個欄位的配置可以通過多個pgsearch.field()產生,且它們之間應使用“||”符號進行串連。更多詳情請參見本表格的內容。

Record

pgsearch目前支援三種Record。

  • raw:不做分詞處理。

  • freq:記錄行ID以及詞項頻率。

  • position:記錄行ID、詞項頻率和出現位置。

分詞器

pgsearch外掛程式內建了多種分詞器,包括jieba、ngram、lindera、en_stem、whitespace等常用的分詞器,能夠滿足您大部分的需求,無需單獨安裝pg_jieba或者zhparser分詞外掛程式。

分詞器名稱

描述

配置

default

根據空格和標點符號進行文本分詞,並轉換為小寫。過濾掉大於255位元組的詞項。

{type: "default"}

raw

不做分詞處理。

{type: "raw"}

en_stem

根據空格和標點符號進行文本分詞,並轉換為小寫,最後再提取每個詞的詞幹。過濾掉大於40個字元的詞項。

{type: "en_stem"}

whitespace

根據空格分詞。

{type: "whitespace"}

ngram

通過根據指定參數將文本分詞成重疊的子字串進行文本分詞。

  • min_gram:定義n-gram的最小長度。例如,設定為2,產生的最小詞項長度將是2個字元。

  • max_gram:定義n-gram的最大長度。例如,設定為5,產生的最大詞項長度將是5個字元。

  • prefix_only: 如果設定為true,分詞器僅產生從詞頭開始的n-gram,確保了首碼的遞進。如果為false,n-gram將從min_gram和max_gram範圍內的所有可能字元組合中產生。

{type: "ngram", min_gram: 1, max_gram: 2, prefix_only: true}

chinese_compatible

考慮中文字元的細微差別而分詞文本,基於空格和標點符號分詞。對於連續的非中文字元,會產生一個token;對於單個中文字元,會產生單獨一個token;對於標點符號等非數字或者字母的字元,會忽略掉不產生token。例如,對於字串“我愛吃橙子 oranges!12”,會產生"我,愛,吃,橙,子,oranges,12"這7個token。

{type: "chinese_compatible"}

chinese_lindera

使用Lindera分詞器分詞文本,它使用CC-CEDICT詞典來分段和分詞文本。

{type: "chinese_lindera"}

korean_lindera

使用Lindera分詞器分詞文本,它使用KoDic詞典來分段和分詞文本。

{type: "korean_lindera"}

japanese_lindera

使用Lindera分詞器分詞文本,它使用IPADIC詞典來分段和分詞文本。

{type: "japanese_lindera"}

jieba

使用jieba分詞器對文本分詞,適用於大多數中文文本。 jieba分詞器支援自訂分詞詞典和停用詞詞典。詳情請參見配置自訂分詞詞典配置停用詞詞典

  • hmm:預設值為true。設定為true時,分詞器將使用HMM(Hidden Markov Model)處理未登入詞。HMM輔助分詞通過上下文資訊判斷詞邊界,從而提升分詞的準確性。在詞典相對完善的情況下,可以將其設定為false,以禁用HMM輔助分詞,提高分詞的處理速度。

  • search:預設值為true。設定為true時,文本將按照最細粒度分詞。這將對長詞再次切分,增加短語的匹配度。設定為false時,文本將按照粗粒度分詞。例如,文本“南京市長江大橋”,search設定為true時被分為“南京/京市/南京市/長江/大橋/長江大橋”。search設定為false時被分為“南京市/長江大橋”。

說明

僅v7.2.1.0及以上的核心版本支援hmm和search參數。

{type: "jieba",hmm=>true,search=>true}

pgsearch.tokenizer()函數用於產生分詞器的配置串,避免手動構造配置串所帶來的不便。其文法和參數說明如下。

文法

pgsearch.tokenizer(<name>, <min_gram>, <max_gram>, <prefix_only>, <search>, <hmm>, <dict>,<stopword>,<lowercase>,<remove_long>, <stemmer>);

參數說明

  • name:文本類型,分詞器的名稱,可取值請參見分詞器

  • 關於min_grammax_gramprefix_onlysearchhmm參數詳情,請參見分詞器

  • dict:文本類型,用於指定jieba分詞器使用的分詞詞典。詳情請參見配置自訂分詞詞典

  • stopword:文本類型,停用詞詞典,預設不配置。詳情請參見配置停用詞詞典

  • lowercase:布爾類型,預設為true,將關鍵詞轉換為小寫

  • remove_long:整型,預設不配置。配置後將移除長度大於等於remove_long位元組數的關鍵詞。每個中文字元佔用3個位元組。

  • stemmer:文本類型,預設不配置。配置後將提取詞幹,例如將runrunningrunsran縮減為 run。無論使用者搜尋哪個run,都可以檢索到相關結果。詞幹提取僅支援英文,對應的取值為en

重要

僅v7.2.1.0及以上的核心版本支援pgsearch.tokenizer()函數。且v7.2.1.0及以上的核心版本必須使用pgsearch.tokenizer()函數建立索引。否則jieba分詞器的自訂分詞詞典和停用詞詞典將無法生效。

建立索引樣本

  • 使用text_fields建立索引。

    -- 使用ngram分詞器,注意,ngram的所有配置欄位都必須顯示給出
    CALL pgsearch.create_bm25(
        index_name => 'search_idx',
        table_name => 'mock_items',
        text_fields => '{description: { tokenizer: {type: "ngram", min_gram: 2, max_gram: 3, prefix_only: false}}}'
    );
    
    -- 使用jieba分詞器
    CALL pgsearch.create_bm25(
        index_name => 'search_idx',
        table_name => 'mock_items',
        text_fields => '{description: { tokenizer: {type: "jieba"}}}'
    );
    
    -- 使用lindera分詞器
    CALL pgsearch.create_bm25(
        index_name => 'search_idx',
        table_name => 'mock_items',
        text_fields => '{description: { tokenizer: {type: "chinese_lindera"}}}'
    );
    --在多欄位上建立索引
    CALL pgsearch.create_bm25(
        index_name => 'search_idx',
        table_name => 'mock_items',
        text_fields => '{description: {fast: false, filednorms: true, tokenizer: {type: "jieba"}}, category: {}}',
        datetime_fields => '{created_at: {fast: true}, last_updated_date: {fast: true}}',
        numeric_fields => '{rating: {fast: true}}',
        json_fields => '{metadata: {fast: true, expand_dost: true, tokenizer: {type: "en_stem"}, record: "position"}}',
        boolean_fields => '{in_stock: {fast: true} }'
    );
    
    --大部分情境下,只需要對text_fileds以及json_fields中的欄位按需配置tokenizer,剩餘參數通常採用預設值即可。即:
    CALL pgsearch.create_bm25(
        index_name => 'search_idx',
        table_name => 'mock_items',
        text_fields => '{description: {tokenizer: {type: "jieba"}}, category: {}}',
        datetime_fields => '{created_at: {}, last_updated_date: {}}',
        numeric_fields => '{rating: {}}',
        json_fields => '{metadata: {tokenizer: {type: "en_stem"}}}',
        boolean_fields => '{in_stock: {} }'
    );
  • 使用pgsearch.field()pgsearch.tokenizer()函數建立索引、查看分詞效果等。

    -- description列的fast設定為true,record設定為'position',分詞器為jieba分詞器(配置了非search模式,使用自訂分詞詞典user_dict、使用內建停用詞 CN_SIMPLE
    -- category列全部使用預設配置
    -- 兩個列的配置可以用 '||' 串連
    CALL pgsearch.create_bm25(
        index_name => 'search_idx',
        table_name => 'mock_items',
        text_fields => pgsearch.field('description', fast=>true, record=>'position', tokenizer=>pgsearch.tokenizer('jieba', search=>false, dict=>'user_dict', stopword=>'CN_SIMPLE')) 
                        || pgsearch.field('category')
    );
    
    CALL pgsearch.create_bm25(
        index_name => 'search_idx',
        table_name => 'mock_items',
        text_fields => pgsearch.field('description', tokenizer=>pgsearch.tokenizer('jieba'),
        datetime_fields => '{created_at: {}, last_updated_date: {}}',
        numeric_fields => '{rating: {}}',
        json_fields => '{metadata: {tokenizer: {type: "en_stem"}}}',
        boolean_fields => '{in_stock: {} }'
    );
    
    -- 使用指定的jieba分詞器查看分詞效果
    SELECT pgsearch.tokenizer(pgsearch.tokenizer('jieba', hmm=>false, search=>false, dict=>'custom_dict_1'), '永和服裝飾品有限公司');
             tokenizer         
    
    -- 使用各類Filter對分詞結果進行處理
    SELECT pgsearch.tokenizer(
        pgsearch.tokenizer('jieba',
        search=>false, dict=>'user_dict', stopword=>'CN_SIMPLE',
        lowercase=>false, remove_long=>27, stemmer=>'en')::text,
        '永和服裝飾品有限公司。Shoping'
    );

查看索引配置

SELECT * FROM pgsearch.schema_bm25('index_name'::regclass);

刪除索引

DROP INDEX index_name;

重建索引

REINDEX INDEX index_name;

查詢文法

@@@排序操作符

@@@排序操作符主要用於KNN檢索,即需要將檢索結果按照BM25得分排序,然後按需擷取TOP結果。

文法

SELECT * FROM <table_name> 
ORDER BY <index_col> @@@ pgsearch.config('<query>');

參數說明

  • <table_name>:表的名稱。

  • <index_col>可以是建立索引時指定的任意一個索引欄位。建議使用在檢索關鍵詞query中出現的第一個索引欄位

  • <query>:檢索的關鍵詞。

  • pgsearch.config:不僅接受檢索字串外,還接受其他檢索對象。檢索對象是可以組合的,允許任意粒度的檢索。實際上,當傳遞檢索關鍵詞給pgsearch.config時,隱式地利用pgsearch.parse將檢索關鍵詞解析為檢索對象。下面樣本中兩個查詢是相同的效果。

  • SELECT * FROM mock_items 
    ORDER BY description @@@ pgsearch.config('description:socks');
    
    SELECT * FROM mock_items ORDER BY description @@@ pgsearch.config(
      query => pgsearch.parse('description:socks')
    );

基礎查詢

指定欄位檢索

文字欄位檢索

檢索包含指定短語的文本。如果短語中包含空格,應使用雙引號將該短語包裹起來。

以下查詢將分別檢索含“keyboard”的行和含“hello world”的行。

SELECT * FROM mock_items 
ORDER BY description @@@ pgsearch.config('description:keyboard');

-- 帶有空格的短語
SELECT * FROM mock_items 
ORDER BY description @@@ pgsearch.config('description:"hello world"');

JSON欄位檢索

以下查詢將檢索含{"metadata": {"color": "white"}}的行。

SELECT * FROM mock_items 
ORDER BY metadata @@@ pgsearch.config('metadata.color:white');

DATETIME欄位檢索

在DATETIME欄位上檢索時,預設採用UTC時區和RFC3339格式。

SELECT * FROM mock_items ORDER BY created_at @@@ pgsearch.config('created_at:"2023-05-01T09:12:34Z"') LIMIT 10;

SELECT * FROM mock_items ORDER BY created_at @@@ pgsearch.config('created_at:"2023-05-01T04:12:34-05:00"') LIMIT 10;

鄰近性操作符檢索

slop~運算子用於匹配中間有單詞分隔的短語。例如,description欄位存在“ergonomic metal keyboard”,由於單詞“ergonomic”和“keyboard”之間有一個單詞分隔,因此以下查詢將找到“ergonomic metal keyboard”。

SELECT * FROM mock_items ORDER BY description @@@ pgsearch.config('description:"ergonomic keyboard"~1');

高效過濾檢索

過濾器只適用於已建立BM25索引的數值欄位(numeric_fields)和布爾欄位(boolean_fields)。與標準SQL語句中WHERE子句相比,過濾檢索可以縮短檢索時間。

SELECT * FROM mock_items ORDER BY description @@@ pgsearch.config('description:keyboard AND rating:<4');

提升排名檢索

如果您希望提升檢索關鍵詞的結果排名,可以使用^字元加提升係數實現。該係數作用於關鍵詞匹配的結果,提高BM25得分,從而提升這些匹配行在結果中的排名。

SELECT * FROM mock_items ORDER BY description @@@ pgsearch.config('description:keyboard^2 OR category:electronics^3');

布林運算子檢索

ANDORNOT可用於組合并篩選多個關鍵詞。括弧可用於分組和控制運算順序。

SELECT * FROM mock_items ORDER BY description @@@ pgsearch.config('description:keyboard OR category:toy');

集合運算子檢索

集合運算子使用一個或者多個OR。優點:更節省CPU資源。

在集合運算子中,每個短語以空格分隔,且每個短語的分詞結果不得超過一個token。由於中文分詞後的token數量取決於分詞器,難以進行有效控制,因此集合運算子只適用於英文,不適用於中文。在中文情境下建議使用多個OR代替此文法。

SELECT * FROM mock_items ORDER BY description @@@ pgsearch.config('description:IN [keyboard toy]');

限制和位移

支援OFFSETLIMIT語句。

SELECT * FROM mock_items
ORDER BY description @@@ pgsearch.config('description:socks') OFFSET 2 LIMIT 10;

進階查詢

擷取分詞結果

通過pgsearch.tokenizer()函數擷取分詞結果。函數返回一個數組,數組元素是分詞後的關鍵詞。

文法

SELECT pgsearch.tokenizer(<tokenizer_config>, <query_str>);

參數說明

  • tokenizer_config:包含分詞器配置資訊的JSON字串,也可以使用同名的pgsearch.tokenizer()組建組態串,更多詳情請參見分詞器

  • query_str:需要被分詞的字串。

使用樣本

SELECT pgsearch.tokenizer('{type: "ngram", min_gram: 1, max_gram: 2, prefix_only: true}', 'hell');
SELECT pgsearch.tokenizer('{type: "jieba"}', '資料倉儲');
SELECT pgsearch.tokenizer(pgsearch.tokenizer('jieba'), '永和服裝飾品有限公司');

詞集合檢索(term_set)

檢索包含任意一個關鍵詞的行。

使用樣本

SELECT * FROM mock_items ORDER BY description @@@ pgsearch.config(
    query =>  pgsearch.term_set(
	    terms => ARRAY[
	        pgsearch.term(field => 'description', VALUE => 'socks'),
	        pgsearch.term(field => 'description', VALUE => 'novel')
            
	    ]
	)
);

參數說明

  • field:指定用於檢索的欄位。如果省略,將檢索所有索引欄位。

  • terms:檢索對象ARRAY。

說明

分詞器預設將入庫的關鍵詞轉換為小寫。因此,在pgsearch.term中使用大寫的關鍵詞將無法查詢到相關行,建議使用小寫關鍵詞查詢。

短語檢索(phrase)

檢索包含所有關鍵詞且符合關鍵詞順序的行。短語檢索需要索引的record配置為position。

使用樣本

SELECT * FROM mock_items ORDER BY description @@@ pgsearch.config(
    query => pgsearch.phrase(
    field => 'description',
    phrases => ARRAY['little', 'red', 'riding' 'hood'],
        slop => 0
    )
);

參數說明

  • field:指定用於檢索的欄位。如果省略,將檢索所有索引欄位。

  • phrases:關鍵詞數組。要求文本包含數組中的所有關鍵詞,且這些詞在文本中出現的順序與數組中關鍵詞的順序一致。只有詞語匹配到全部關鍵詞,且詞語的順序與關鍵詞的順序一致時,才會返回該行。

  • slop:選擇性參數,表示各個關鍵詞之間的最大距離。slop值為0,表示詞語在文本中出現的順序與關鍵詞的順序一致,並且相鄰。例如,'little' 'red' 'riding' 'hood'按順序連續出現,才算滿足匹配條件。如果slop的值大於0,表示允許關鍵詞之間可以有一定的間隔,也就是說'little' 'red' 'riding' 'hood'中間可以有其他詞。

短語首碼檢索(phrase_prefix)

檢索包含指定關鍵詞且符合關鍵詞順序(包含檢索詞首碼功能)的行。短語首碼檢索需要對被檢索欄位建立索引。

使用樣本

SELECT * FROM mock_items ORDER BY description @@@ pgsearch.config(
    query => pgsearch.phrase_prefix(
    field => 'description',
    phrases => ARRAY['little', 'red', 'riding' 'hood'],
        max_expansion => 1
    )
);

參數說明

  • field:指定用於檢索的欄位。如果省略,將檢索所有索引欄位。

  • phrases:關鍵詞數組。query表示檢索的關鍵詞序列。數組裡面的關鍵詞序列作為首碼,可匹配到指定檢索關鍵詞後有任一字元的字串(須順序一致)。例如:ARRAY['little', 're'] ,首碼為“little re”,因此可以匹配到“little red riding hood”。

  • max_expansion:選擇性參數,限制首碼在檢索過程中可以擴充的關鍵詞變體的數量。即該參數設定限制了關鍵詞匹配的變體數量的上限,縮小了檢索的範圍。

分詞檢索(tokenizer_terms

使用指定的分詞器對查詢文本做分詞處理,隨後查詢分詞後的token。支援在指定token之間應用布爾邏輯。

使用樣本

SELECT * FROM mock_items ORDER BY description @@@ pgsearch.config(
pgsearch.tokenizer_terms('description', '朝陽百貨', pgsearch.tokenizer('jieba'), 'OR'));

參數說明

  • tokenizer: 使用pgsearch.tokenizer()指定的分詞器配置串,預設為jieba分詞器。

  • operator:用於解釋分詞後token之間的布爾邏輯,取值為ORAND,預設為OR。例如“朝陽百貨”分詞後為“朝陽/百貨”。當operatorOR時,查詢結果會返回包含“朝陽”或“百貨”的行。當operatorAND時,查詢結果只會返回同時包含“朝陽”和“百貨”的行。

全部檢索(all)

此檢索類型無區別地匹配索引欄位中的每個結果行,並為每一行分配一個統一的分數1.0。即每一行的分數一樣,檢索結果也不分優先順序。

SELECT * FROM mock_items ORDER BY description @@@ pgsearch.config(
    query =>  pgsearch.all()
);

布爾檢索(boolean)

布爾檢索根據子查詢定義的邏輯關係過濾匹配結果行。

使用樣本

SELECT * FROM mock_items ORDER BY description @@@ pgsearch.config(
    query => pgsearch.boolean(
	    should => ARRAY[
		    pgsearch.parse('description:socks'),
		    pgsearch.phrase_prefix(field => 'description', phrases => ARRAY['book']),
		    pgsearch.term(field => 'description', VALUE => 'writer'),
		    pgsearch.fuzzy_term(field => 'description', VALUE => 'wow')
	    ],
        must_not => ARRAY[
            pgsearch.term(field => 'description', VALUE => 'writer')
        ],
        must => ARRAY[
            pgsearch.term(field => 'rating', VALUE => 4)
        ]
    )
);
-- 可以只配置should、must_not、must中的一個或幾個
SELECT * FROM mock_items ORDER BY description @@@ pgsearch.config(
    query => pgsearch.boolean(
	    should => pgsearch.parse('description:socks')
    )
);

參數說明

  • must:一組ARRAY檢索對象作為必須匹配的條件。只有滿足所有must的行才會出現在檢索結果中。

  • must_not:一組ARRAY檢索對象作為不得匹配的條件。滿足任意must_not條件的行會被排除在檢索結果中。

  • should:一組ARRAY檢索對象作為條件,當must不存在時,其中至少有一個必須匹配。

  • must不存在時,滿足至少一個should條件的行會出現在檢索結果中。

提升排名檢索(boost)

提升查詢作用於子查詢(即以下樣本中query => pgsearch.parse('description:socks'))以放大其得分影響,從而提升子查詢的結果排名。

使用樣本

SELECT * FROM mock_items ORDER BY description @@@ pgsearch.config(
    query => pgsearch.boost(query => pgsearch.parse('description:socks'), boost => 2)
);

參數說明

  • boost:與每個結果的得分相乘的因子。

  • query:檢索對象。

恒等分數檢索(const_score)

在與子查詢(即以下樣本中的query => pgsearch.all())匹配的所有行中應用常量分數。它可以避免在子查詢上進行不必要的分數計算。

使用樣本

SELECT * FROM mock_items ORDER BY description @@@ pgsearch.config(
    query => pgsearch.const_score(query => pgsearch.all(), score => 2)
);

參數說明

  • score:用於子查詢的每個結果的恒定得分。

  • query:檢索對象。

最大析取檢索(disjunction_max)

最大析取檢索返回與一個或多個指定子查詢匹配的行。如果某行符合的匹配條件越多,則該行的得分越高。

使用樣本

SELECT * FROM mock_items ORDER BY description @@@ pgsearch.config(
    query => pgsearch.disjunction_max(
      disjuncts => ARRAY[
          pgsearch.parse('description:socks'),
          pgsearch.parse('description:Generic')
      ],
      tie_breaker => 0.75
    )
);

參數說明

  • disjuncts: 子查詢對象數組,可以包含一個或多個子查詢。

  • tie_breaker:可選配置,用於某行匹配多個子查詢時,調整該行的BM25得分。當某行同時滿足多個子查詢時,該行的BM25得分計算規則:首先計算所有匹配子查詢中最高的BM25得分,然後對於每個額外匹配的子查詢,會計算遞增分數,最後計算BM25總分。在上面的例子中,假設有一行與子查詢pgsearch.parse('description:socks')的BM25得分為1.0,與子查詢pgsearch.parse('description:Generic')的BM25得分為0.5,那麼該行最終的BM25得分為1.0+0.75*0.5=1.375。

空匹配(empty)

空匹配用作預留位置,不匹配任何行。它可用於測試情境或特定邊緣情況。

SELECT * FROM mock_items ORDER BY description @@@ pgsearch.config(
    query => pgsearch.empty()
);

模糊檢索(fuzzy_term)

模糊檢索可讓使用者獲得與檢索關鍵詞大致匹配的檢索結果,能夠容忍細微的拼字錯誤。即使拼字不完全正確,也能檢索到相關結果。

使用樣本

SELECT * FROM mock_items ORDER BY description @@@ pgsearch.config(
    query => pgsearch.fuzzy_term(
      field => 'description', 
      VALUE => 'wow',
      distance => 2,
      tranposition_cost_one => true,
      prefix => true)
);

參數說明

  • field:指定用於檢索的欄位。如果省略,將檢索所有索引欄位。

  • value:指定檢索的關鍵詞,使用基於Levenshtein距離的模糊比對來檢索與該關鍵詞相似的結果。

  • distance:可選配置,預設值為2。將索引欄位中的詞語視為檢索關鍵詞匹配的允許最大編輯距離(即單字元編輯),最大值為2。

  • tranposition_cost_one:可選配置,預設值為true。當設定為true,在Levenshtein距離計算中,交換(交換兩個相鄰的字元)被認為是單個編輯。當設定為false,其被認為是兩個單獨的編輯(刪除和插入)。

  • prefix:可選配置,預設值為true。當設定為true,檢索關鍵詞的首碼不參與模糊編輯距離計算。設定為false時,則將整個字串用於計算。

範圍檢索(range)

檢索包含屬於指定值範圍的行,可以用在參數numeric_fields和datetime_fields。

使用樣本

SELECT * FROM mock_items ORDER BY rating @@@ pgsearch.config(
    query => pgsearch.range(
        field => 'rating',
        RANGE => '[1,4)'::int4range
  )
);

參數說明

  • field:指定用於檢索的欄位。如果省略,將檢索所有索引欄位。

  • range:指定與欄位匹配的值範圍。範圍支援的類型包括INT4RANGE、INT8RANGE、DATERANGE、TSRANGE和TSTZRANGE。

Regex檢索(regex)

如果某行中的詞語能夠匹配指定的Regex,則返回該行。

使用樣本

SELECT * FROM mock_items ORDER BY description @@@ pgsearch.config(
    query => pgsearch.regex(
		field => 'description',
		PATTERN => '(glass|screen|like|cloth|phone)'
	)
);
SELECT * FROM mock_items ORDER BY description @@@ pgsearch.config(
    query => pgsearch.regex(
		field => 'description',
		PATTERN => '(.*screen.*)'
	)
);

參數說明

  • field:指定用於檢索的欄位。如果省略,將檢索所有索引欄位。

  • pattern:Regex模式字串。

其他

擷取BM25得分

將@@@操作符前置,並使用AS文法擷取BM25得分。

因為AnalyticDB for PostgreSQL資料庫中預設的ORDER BY是升序,而BM25得分是越大越好,因此,返回的實際上是BM25得分的負值。例如,BM25得分為2.86,那麼返回的結果為-2.86。除此之外,只有在text_fields和json_fields上的檢索才會計算BM25得分,對於numeric_fields、datetime_fields和boolean_fields類型的檢索,是無法計算BM25得分的。

文法

SELECT *, mock_items @@@ pgsearch.config(<query>) as BM25
FROM mock_items
ORDER BY BM25;

使用樣本

-- 1.只在字串類型的欄位上進行檢索,也就是最常見的全文檢索索引,可以返回BM25得分
SELECT description, rating, description @@@ pgsearch.config('description:socks') AS bm25 FROM mock_items ORDER BY bm25 limit 1;

-- 2.在字串類型的欄位上進行全文檢索索引,同時基於數實值型別的欄位進行過濾,同樣可以返回BM25得分
SELECT description, rating, description @@@ pgsearch.config('description:socks AND rating:4') AS bm25 FROM mock_items ORDER BY bm25 limit 4;
 
-- 3.在json欄位上進行全文檢索索引,同樣可以返回BM25得分
SELECT metadata, metadata @@@ pgsearch.config('metadata.color:White') AS bm25 FROM mock_items ORDER BY bm25 LIMIT 1;

-- 4.在rank欄位上進行範圍過濾,無法計算BM25得分,返回預設值-1
 SELECT description, rating, rating @@@ pgsearch.config('rating:[4 TO 5]') AS bm25 FROM mock_items ORDER BY bm25 LIMIT 1;

查詢結果

 -- 1.只在字串類型的欄位上進行檢索,也就是最常見的全文檢索索引,可以返回BM25得分
   description  | rating |    bm25    
---------------+--------+------------
 Generic socks |      4 | -2.1048825
(1 row)

-- 2.在字串類型的欄位上進行全文檢索索引,同時基於數實值型別的欄位進行過濾,同樣可以返回BM25得分
 description  | rating |    bm25    
---------------+--------+------------
 Generic socks |      4 | -3.1081846
(1 row)

-- 3.在json欄位上進行全文檢索索引,同樣可以返回BM25得分
                metadata                 |   bm25    
-----------------------------------------+-----------
 {"color": "White", "location": "China"} | -3.453373
(1 row)

-- 4.在rank欄位上進行範圍過濾,無法計算BM25得分,返回預設值-1
  description    | rating | bm25 
------------------+--------+------
 Plastic Keyboard |      4 |   -1
(1 row)