搜索查询扩展

本页面介绍了如何使用查询增强功能进行全文搜索

为了提高找到相关结果的可能性,Spanner 提供了高级功能,可扩展搜索查询以包含相关字词、同义词和拼写更正。Spanner 提供以下查询增强选项:

增强型查询

如需使用增强型查询,请在 SEARCH 函数中设置 enhance_query=>true。然后,Spanner 会自动扩展搜索查询,包括相关字词和同义词、应用词干提取,以及进行拼写更正。例如,使用增强型查询时,搜索查询 hotl cal 会匹配专辑 Hotel California

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'hotl cal', enhance_query=>true)

PostgreSQL

SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'hotl cal', enhance_query=>true)

enhance_query 是一种查询时选项,不会影响词元化。无论是否使用 enhance_query,您都可以使用相同的搜索索引。

Google 在不断改进查询增强算法。因此,包含 enhance_query => true 的查询可能会随着时间推移生成略有不同的结果。

使用 enhance_query 可能会因扩展搜索查询和执行生成的较大查询而增加延迟。

自定义字典

您可以将自定义字典与 Spanner 全文搜索搭配使用,为数据集中的字词定义同义词。这有助于捕获同义词、首字母缩略词、等效字词和其他字词变体,从而改进搜索结果的检索。

创建自定义字典表

自定义字典是用户创建的表格,其中包含字词及其同义词的键值对。如需创建此类表,请在 CREATE TABLE 语句中添加 fulltext_dictionary_table = true 选项。该表必须包含两列:

  • Key:一个不可为 null 的字符串列,用于存储要通过同义词进行扩展的字词。
  • Value:一个不可为 null 的字符串数组列,用于存储键的同义词数组。

表中不能有 KeyValue 以外的任何列。 如果搜索字词与字典中的 Key 相匹配,则搜索范围会扩大,以涵盖 Value 中的所有相应同义词以及关键字词本身。 以下示例创建了一个名为 MyCustomDictionary 的自定义字典表。您还必须在创建此表期间设置表选项 fulltext_dictionary_table=true

GoogleSQL

CREATE TABLE MyCustomDictionary (
  Key STRING(MAX) NOT NULL,
  Value ARRAY<STRING(MAX)> NOT NULL,
) PRIMARY KEY(Key),
OPTIONS (fulltext_dictionary_table = true);

PostgreSQL

CREATE TABLE mycustomdictionary (
  key character varying  NOT NULL,
  value character varying [] NOT NULL,
  PRIMARY KEY(key)
)  WITH ( type = 'fulltext_dictionary')

创建表格后,插入同义词:

GoogleSQL

INSERT INTO MyCustomDictionary (Key, Value) VALUES
('album', ['vinyl', 'cassette']),
('edm', ['electronic dance music']);

PostgreSQL

INSERT INTO mycustomdictionary (key, value) VALUES
('album', ARRAY['vinyl', 'cassette']),
('edm', ARRAY['electronic dance music']);

填充表格时,请注意以下几点:

  • 关键字必须是单个字词。
  • 值可以是单个字词,也可以是多词短语。如果某个值包含多个字词,则在查询扩展期间,系统会将其视为词组搜索。
  • 所有键和值都应采用小写形式。这样可确保它们与搜索令牌匹配,而搜索令牌会由默认的分词器转换为小写。

只有当搜索字词与 Key 相匹配时,才会发生搜索扩展。如果搜索字词与 Value 中的同义词匹配,但不与 Key 匹配,则不会扩展搜索范围。如果您需要双向映射(例如,搜索 vinylcassette 时也能找到 album),您还必须将反向映射插入到字典表中。以下示例展示了如何为 albumvinylcassette 插入双向映射:

GoogleSQL

INSERT INTO MyCustomDictionary (Key, Value)
-- 1. Insert album -> vinyl, cassette
SELECT 'album', ['vinyl', 'cassette']
UNION ALL
-- 2. Insert vinyl -> album and cassette -> album
SELECT syn, ['album']
FROM UNNEST(['vinyl', 'cassette']) AS syn;

PostgreSQL

INSERT INTO mycustomdictionary (key, value)
-- 1. Insert album -> vinyl, cassette
SELECT 'album', ARRAY['vinyl', 'cassette']
UNION ALL
-- 2. Insert vinyl -> album and cassette -> album
SELECT syn, ARRAY['album']
FROM unnest(ARRAY['vinyl', 'cassette']) AS syn;

在搜索查询中使用自定义字典

如需使用自定义字典,请在 SEARCH 函数的 dictionary 实参中指定字典表名称。

  • 如果搜索字词是字典中的键,SEARCH 还会查找其值。字词 album 与包含 vinylcassette 的邮件匹配。

    GoogleSQL

    SELECT MessageId, Body
    FROM Messages
    WHERE SEARCH(Body_Tokens, 'album', dictionary=>'MyCustomDictionary');
    

    PostgreSQL

    SELECT messageid, body
    FROM messages
    WHERE spanner.search(body_tokens, 'album', dictionary=>'mycustomdictionary');
    
  • 如果字典值包含多个字词(例如键 edm 的值为 electronic dance music),则系统会将其视为词组搜索。这意味着,只有当搜索字词相邻且按指定的确切顺序出现时,才会被视为匹配。例如,以下查询会返回包含确切词组“electronic dance music”的结果,但不会匹配“dance electronic music”。这主要用于展开缩写,可按以下方式使用:

    GoogleSQL

    SELECT MessageId, Body
    FROM Messages
    WHERE SEARCH(Body_Tokens, 'edm', dictionary=>'MyCustomDictionary');
    

    PostgreSQL

    SELECT messageid, body
    FROM messages
    WHERE spanner.search(body_tokens, 'edm', dictionary=>'mycustomdictionary');
    

字典查找过时程度

默认情况下,自定义字典条目的读取时间不得超过 15 秒。这会减少读取操作的开销,因为读取略微过时的数据比读取最新数据更高效。因此,对字典条目所做的更改可能需要最多 15 秒才能反映在搜索查询中。您可以通过以下方式替换此行为:

  • 使用 fulltext_dictionary_staleness 表格选项。
  • 使用 fulltext_dictionary_staleness 查询提示实现更精细的控制。

如果同时使用查询提示和表选项,查询提示会替换表选项。

fulltext_dictionary_staleness 表格选项

您可以为字典表设置 fulltext_dictionary_staleness 选项。使用此字典表的所有查询都将使用此过时性值,除非查询提示替换了该值。

GoogleSQL

以下示例展示了如何使用 fulltext_dictionary_staleness 选项 CREATE 表:

CREATE TABLE MyCustomDictionary (
  Key STRING(MAX) NOT NULL,
  Value ARRAY<STRING(MAX)> NOT NULL,
) PRIMARY KEY(Key),
OPTIONS (
  fulltext_dictionary_table = true,
  fulltext_dictionary_staleness = '5s'
);

以下示例展示了如何使用 ALTER 表格来更改或设置 fulltext_dictionary_staleness 选项:

ALTER TABLE MyCustomDictionary SET OPTIONS (
  fulltext_dictionary_staleness = '60s'
);

PostgreSQL

以下示例展示了如何使用 fulltext_dictionary_staleness 选项 CREATE 表:

-- Create with 5s staleness
CREATE TABLE mycustomdictionary (
  key character varying NOT NULL,
  value character varying[]  NOT NULL,
  PRIMARY KEY(key)
) WITH (
  type = 'fulltext_dictionary',
  fulltext_dictionary_staleness = '5s'
);

PostgreSQL 页面不支持使用 ALTER 表更改或设置 fulltext_dictionary_staleness 选项。

fulltext_dictionary_staleness 查询提示

如需进行更精细的控制,您可以使用 fulltext_dictionary_staleness 查询提示为单个查询指定不同的陈旧程度。此提示会替换表级设置。

以下示例使用提示来执行零过时性的字典表查找。这样可确保读取最新的字典条目。这种方法可能会增加查询延迟时间,因为读取最新数据不如允许一定程度的过时数据高效。

GoogleSQL

@{fulltext_dictionary_staleness="0s"}
SELECT MessageId, Body
FROM Messages
WHERE SEARCH(Body_Tokens, 'Bill', dictionary=>'MyCustomDictionary');

PostgreSQL

/*@ fulltext_dictionary_staleness='0s' */
SELECT messageid, body
FROM messages
WHERE spanner.search(body_tokens, 'Bill', dictionary=>'mycustomdictionary');

自定义字典表的已知限制

  • 使用 Spanner 导入和导出功能时,对自定义字典表的支持有限。
  • 自定义字典表必须在默认架构中创建,而不能在命名架构中创建。
  • 自定义字典表仅支持默认的 SEARCH 查询方言

将自定义字典与增强型查询相结合

您可以在 SEARCH 函数中同时设置 dictionaryenhance_query=>true,以将自定义字典同义词与 enhanced query 结合使用。查询增强功能可以通过常见同义词或拼写更正来扩展查询,而自定义字典则允许您定义自己的扩展。例如,如果 enhance_queryalbum 扩展为包含 record,并且 MyCustomDictionaryalbum 映射到 ['vinyl', 'cassette'],则以下查询会匹配包含 albumrecordvinylcassette 的消息:

GoogleSQL

SELECT MessageId, Body
FROM Messages
WHERE SEARCH(Body_Tokens, 'album', enhance_query=>true, dictionary=>'MyCustomDictionary');

PostgreSQL

SELECT messageid, body
FROM messages
WHERE spanner.search(body_tokens, 'album', enhance_query=>true, dictionary=>'mycustomdictionary');

如果同时启用这两项增强功能,它们会独立处理原始搜索字词,并且一项增强功能生成的字词不会用作另一项增强功能的输入。

后续步骤