日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

使用文檔

更新時間:

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

功能簡介

pgsearch插件實現了全新的BM25(Best Matching 25)索引,該索引基于高性能全文檢索引擎Tantivy構建。BM25是許多現代搜索引擎(如 Elasticsearch)的優先選擇。它通過考慮一個詞項在記錄行中出現的頻率和該詞項在記錄行中的獨特性來對行進行排名。當您在記錄行中檢索關鍵詞或短語時,BM25十分有用。BM25索引能夠在云原生數據倉庫 AnalyticDB 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>',
  numeric_fields => '<numeric_fields>',
  boolean_fields => '<boolean_fields>',
  json_fields => '<json_fields>',
  datetime_fields => '<datetime_fields>'
)

參數說明

參數

是否必填

支持的字段類型

說明

index_name

String

索引名稱。

table_name

String

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

schema_name

String

表所在的Schema,默認為當前所在的Schema。

text_fields

至少設置一個。

VARCHAR、TEXT、VARCHAR[]、TEXT[]

定義哪些文本字段被索引及這些字段的索引方式。它接受一個JSON5格式的字符串,其結構為鍵值對。其中鍵對應數據庫表中的字段名稱,值則是一個配置對象。支持的配置如下。

  • fast:默認值為false。該字段可以被迅速隨機訪問,也適用于加速得分和過濾。

  • fieldnorms:默認值為true。存儲文本字段長度的信息。必須為true才能計算BM25得分。

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

  • record:默認值為position。描述索引中包含的信息。record相關配置請參見Record

numeric_fields

INT2、INT4、INT8、OID、XID、FLOAT4、FLOAT8、NUMERIC

定義哪些數值字段被索引以及這些字段的索引方式。它接受一個JSON5格式的字符串,其結構為鍵值對。其中鍵對應數據庫表中的字段名稱,值則是一個配置對象。支持的配置如下。

fast:默認值為true。該字段可以被迅速隨機訪問,也適用于加速得分和過濾。

boolean_fields

BOOLEAN

定義哪些布爾字段被索引以及這些字段的索引方式。支持的配置如下。

fast:默認值為true。該字段可以被迅速隨機訪問,也適用于加速得分和過濾。

json_fields

JSON、JSONB

定義哪些JSON字段被索引以及這些字段的索引方式。其結構為鍵值對。其中鍵對應數據庫表中的字段名稱,值則是一個配置對象。一旦索引創建,就可以在JSON值內的嵌套文本字段上執行檢索。支持的配置如下。

  • fast:默認值為false。該字段可以被迅速隨機訪問,也適用于加速得分和過濾。

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

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

  • record:默認值為position。描述索引中包含的信息。record相關配置請參見Record

datetime_fields

DATE、TIMESTAMP、TIMESTAMPTZ、TIME和TIMETZ

定義哪些日期時間字段被索引以及這些字段的索引方式。如果未指定,檢索詞將使用UTC時區,并且采用RFC3339格式。支持的配置如下。

fast:默認值為true。該字段可以被迅速隨機訪問,也適用于加速得分和過濾。

Record

pgsearch目前支持三種Record。

  • raw:不做分詞處理。

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

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

分詞器

pgsearch支持多種分詞器,詳情如下表。

分詞器名稱

描述

配置

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分詞器進行分詞,適用于大多數中文文本。 更多詳情請參見pg_jieba

{type: "jieba"}

創建索引示例

-- 使用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: {} }'
);

查看索引配置

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')
    );

@@操作符

  • 對于非字符串類型的BM25得分是沒有意義的。如果您不希望將結果按照BM25得分排序,可以使用@@操作符。@@操作符的參數與@@@類似,左邊參數是表名,右邊參數是pgsearch.config函數封裝的查詢條件。不同的是,@@操作符用在WHERE子句里。@@操作符不僅支持indexscan,同時也支持BitmapIndexScan。因此,在獲取大量結果時,性能比@@@操作符更好。如果您不需要將結果按照BM25得分排序,同時需要獲取大量結果,可以使用@@操作符以獲得更好的性能體驗。

  • 語法

  • SELECT * FROM <table_name> 
    WHERE <index_col> @@ pgsearch.config('<query>');
  • 參數說明

  • 參數說明請參見參數說明

基礎查詢

指定字段檢索

文本字段檢索

以下查詢將檢索含“keyboard”的行。

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

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資源。

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;

高級查詢

詞集合檢索(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。

短語檢索(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:可選參數,限制前綴在檢索過程中可以擴展的關鍵詞變體的數量。即該參數設置限制了關鍵詞匹配的變體數量的上限,縮小了檢索的范圍。

全部檢索(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)

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

使用示例

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:正則表達式模式字符串。

其他

獲取分詞結果

  • 通過pgsearch.tokenizer函數獲取分詞結果。函數返回一個數組,數組元素是分詞后的關鍵詞。

    語法

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

    參數說明

    • tokenizer_config:包含分詞器配置信息的JSON字符串。具體請參見分詞器

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

    使用示例

    SELECT pgsearch.tokenizer('{type: "ngram", min_gram: 1, max_gram: 2, prefix_only: true}', 'hell');
    SELECT pgsearch.tokenizer('{type: "jieba"}', '數據倉庫');
  • 通過pgsearch.tokenizer函數和布爾檢索來檢索指定字段上包含任意一個分詞后的token的結果。為了方便使用,提前定義如下函數。

    -- 該函數用于在 `mock_items` 表中檢索指定字段包含任意從輸入字符串通過給定的分詞器配置派生的 token 的記錄。
    -- 參數:
    --  search_col: 指定在`mock_items` 表上的search_col字段上檢索
    --  tokenizer_config: 用于對輸入字符串進行分詞的 JSON 配置。
    --  input_string: 需要進行分詞的字符串。
    -- 返回:
    --  一個包含符合檢索條件的結果的表, 包含 (id, description) 字段。
    CREATE OR REPLACE FUNCTION find_mock_items(search_col text, tokenizer_config text, input_string text)
    RETURNS TABLE(id int, description text) AS $$
    DECLARE
        tokens text[];
        should_conditions text;
    BEGIN
        -- Step 1: Get tokens using pgsearch.tokenizer
        tokens := pgsearch.tokenizer(tokenizer_config, input_string);
        
        -- Step 2: Construct `should` conditions as text
        SELECT string_agg(
            format($f$pgsearch.parse('%I:%s')$f$, search_col, token),
            ', '
        ) INTO should_conditions
        FROM unnest(tokens) AS token;
    
        -- Step 3: Construct the full query as text
        RETURN QUERY EXECUTE format(
            'SELECT id, description FROM mock_items ORDER BY %s @@@ pgsearch.config(
                query => pgsearch.boolean(
                    should => ARRAY[%s]
            )) LIMIT 10',
            search_col,
            should_conditions
        );
    END;
    $$ LANGUAGE plpgsql;

    使用時,需要指定在哪一個字段上檢索、分詞器信息、檢索字符串。值得注意的是,配置的分詞器信息必須和構建索引時,對應字段上的分詞器配置信息一致,否則無法得到期望的結果。您也可以按需修改find_mock_items函數,來滿足不同的需求。

    SELECT * FROM find_mock_items(
        'description',
        '{type: "jieba"}', 
        '數據倉庫'
    );

    查詢結果

     tokenizer 
    -----------
     {h,he}
    (1 row)
    
      tokenizer  
    -------------
     {數據,倉庫}
    (1 row)

獲取BM25得分

將@@@操作符前置,并使用AS語法獲取BM25得分。

因為云原生數據倉庫 AnalyticDB 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)

@@操作符使用示例

示例1

-- 查詢有多少文檔包含“shoes”
SELECT count() FROM mock_items WHERE description @@ pgsearch.config('description:socks');

-- 返回所有包含"shoes"的文檔
SELECT * FROM mock_items WHERE description @@ pgsearch.config('description:socks');

@@操作符支持前文描述的所有基礎查詢和高級查詢語法,例如布爾檢索、正則表達式檢索等。

示例2

SELECT * FROM mock_items WHERE 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)
        ]
    )
);