# 全文搜索

注意

本指南仅适用于 DB 版本 1.5.0 或更高版本。

多年来,传统数据库的文本搜索功能一直是基础功能,使用 LIKEILIKE 等操作符。然而,由于存在以下几个限制,它们无法满足现代信息检索系统的需求:

  • 缺乏语言支持: 传统方法难以处理语言细微差别,无法识别词语的派生形式(例如,“satisfies” 和 “satisfy”),这可能导致搜索结果不完整或不准确。虽然可以使用 OR 手动搜索各种变体,但这种方法繁琐且容易出错。
  • 缺乏结果排序: 没有排序搜索结果的能力,导致在成千上万个匹配项中进行筛选变得低效。
  • 性能问题: 缺乏索引支持意味着每次搜索都必须处理每个文档,导致性能较慢。

为了克服这些挑战,MyScale 引入了一种名为 FTS 索引(全文搜索索引)的新索引类型,由 Tantivy (opens new window) 库提供支持,这是一个高性能的开源全文搜索引擎库。FTS 索引支持 BM25 索引算法,能够实现高效和相关的搜索结果。这种集成增强了 MyScale 的全文搜索功能,并提高了整体性能。

# 教程概述

本教程将指导您进行三种类型的 FTS 索引搜索实验:

MyScale 中的 FTS 索引示意图

在开始之前,请确保您已经设置了 MyScale 集群。有关设置说明,请参阅我们的 快速入门指南 (opens new window)

# 数据集概述

我们将使用 Wikipedia 摘要数据集 (opens new window),其中包含超过 560 万条记录,以 Parquet 格式提供。此数据集将直接从 S3 导入到 MyScale 中,无需进行本地下载。

下表简要描述了此数据集的内容。

id body title url
... ... ... ...
77 Jake Rodkin is an American .... and Puzzle Agent. Jake Rodkin https://en.wikipedia.org/wiki/Jake_Rodkin (opens new window)
78 Friedlandpreis der Heimkehrer is ... of Germany. Friedlandpreis der Heimkehrer https://en.wikipedia.org/wiki/Friedlandpreis_der_Heimkehrer (opens new window)
... ... ... ...

# 创建和填充表格

使用以下 SQL 命令在 MyScale 中创建 en_wiki_abstract 表格:

CREATE TABLE default.en_wiki_abstract(
    `id` UInt64,
    `body` String,
    `title` String,
    `url` String,
)
ENGINE = MergeTree
ORDER BY id;

然后,从 S3 导入数据集。请耐心等待数据导入完成。

INSERT INTO default.en_wiki_abstract SELECT * FROM s3('https://myscale-datasets.s3.ap-southeast-1.amazonaws.com/wiki_abstract_5m.parquet','Parquet');

验证表格包含 5,648,453 行数据。

SELECT count(*) FROM default.en_wiki_abstract;

输出:

count()
5648453

为了提高搜索性能,我们可以通过将表格合并为单个数据部分来优化表格。此步骤是可选的。

OPTIMIZE TABLE default.en_wiki_abstract FINAL;

运行以下 SQL 语句,检查此表格中的数据是否已压缩为一个部分。

SELECT COUNT(*) FROM system.parts
WHERE table = 'en_wiki_abstract' AND active = 1;

如果数据已压缩为 1 个部分,则此 SQL 语句将返回以下结果集:

count()
1

# 理解 FTS 索引参数

MyScale 支持多种分词器,每种分词器适用于不同的场景。在创建 FTS 索引时,您可以使用 JSON 配置为分词器自定义配置。

提示

请在 FTS 索引的参数中提供有效的 JSON 字符串。

-- 示例 1:创建一个没有指定参数的索引,使用默认配置
ALTER TABLE [table_name] ADD INDEX [index_name] [column_name]
TYPE fts;
-- 示例 2:使用默认分词器创建索引
ALTER TABLE [table_name] ADD INDEX [index_name] [column_name]
TYPE fts('{"[column_name]":{"tokenizer":{"type":"default"}}}');
-- 示例 3:使用 stem 分词器并应用停用词
ALTER TABLE [table_name] ADD INDEX [index_name] [column_name]
TYPE fts('{"[column_name]":{"tokenizer":{"type":"stem", "stop_word_filters":["english"]}}}');

下表列出了 FTS 索引支持的分词器类型。

分词器类型 描述
default 默认分词器,按非字母字符拆分文本,不区分大小写
raw 原始分词器,在文本上不执行分词,将整个文本视为单个标记
simple 简单分词器,按非字母字符拆分文本
stem 词干分词器,支持多种语言,将单词转换为其词干形式,可以忽略单词时态
whitespace 空格分词器,按空格字符(空格、制表符、换行等)拆分文本
ngram N-gram 分词器,根据指定的 n-gram 长度拆分文本
chinese 中文分词器,对中文文本进行分词,内部使用 jieba 分词库进行分词

# 常见分词器参数

rawstem 分词器仅支持 store_doc 参数,其他分词器除了支持上述常见参数外,还支持以下常见参数。

参数名称 类型 默认值 描述
store_doc 布尔型 false 是否存储原始文档,目前不建议启用
length_limit 数字 40 分词标记的最大长度
case_sensitive 布尔型 false 分词是否区分大小写

除了上述常见参数外,大多数分词器还支持其他参数。

# simplestemwhitespace 分词器

参数名称 类型 默认值 描述
stop_word_filters 字符串数组 [] 停用词过滤器,指定在分词过程中要丢弃的停用词的语言,所有有效的语言包括 ["danish", "dutch", "english", "finnish", "french", "german", "hungarian", "italian", "norwegian", "portuguese", "russian", "spanish", "swedish"]

# stem 分词器

参数名称 类型 默认值 描述
stem_languages 字符串数组 [] 用于词干处理的语言,对于英语,它可以在分词过程中忽略单词时态,词干分词器支持的语言有 ["arabic", "danish", "dutch", "english", "finnish", "french", "german", "greek", "hungarian", "italian", "norwegian", "portuguese", "romanian", "russian", "spanish", "swedish", "tamil", "turkish"]

# ngram 分词器

参数名称 类型 默认值 描述
min_gram 数字 2 最小的 n-gram 数
max_gram 数字 3 最大的 n-gram 数
prefix_only 布尔型 false 是否仅从单词的前缀提取 n-gram

# chinese 分词器

对于中文分词器,使用 cang-jie (opens new window) 作为底层实现。

参数名称 类型 默认值 描述
jieba 字符串 "default" "default" 表示使用 jieba 字典,"empty" 表示不使用内置的 jieba 字典进行分词。有效值为 "default""empty"
mode 字符串 "search" 中文分词模式,有效值为 "all"、"default"、"search" 或 "unicode",每种模式之间的区别可以参考 cang-jie/options.rs (opens new window)
hmm 布尔型 false 是否启用 HMM

上述内容详细描述了 MyScale FTS 索引分词器的参数。在创建 FTS 索引时,您可以选择最适合您需求的分词器类型,并配置其参数以提高搜索性能和结果。

# 创建 FTS 索引

使用适当的分词器自定义您的 FTS 索引,以优化搜索性能。例如,使用带有英语停用词的 stem 分词器可以通过关注单词的词干形式来提高搜索准确性。

ALTER TABLE default.en_wiki_abstract
ADD INDEX body_idx (body)
TYPE fts('{"body":{"tokenizer":{"type":"stem", "stop_word_filters":["english"]}}}');

通常情况下,FTS 索引(类似于 ClickHouse 中的跳过索引)仅适用于新插入的数据,因此仅添加索引不会影响现有数据。要对已存在的数据进行索引,请使用以下语句:

ALTER TABLE default.en_wiki_abstract MATERIALIZE INDEX body_idx;

# 使用文档 BM25 排名进行搜索

注意

第一次执行 TextSearch() 可能会较慢,因为它需要加载 FTS 索引。

以下示例展示了如何使用 TextSearch() 函数。该示例返回与 "non-profit institute in Washington" 最相关的前 10 个文档。用于衡量相关性的指标是 TextSearch() 函数返回的 BM25 分数,分数越高,相关性越高。

SELECT
    id,
    title,
    body,
    TextSearch(body, 'non-profit institute in Washington') AS score
FROM default.en_wiki_abstract
ORDER BY score DESC
LIMIT 5;

从结果中可以看出,每行 body 列的文本与搜索短语 "non-profit institute in Washington" 相关。

id title body score
3400768 Drug Strategies Drug Strategies is a non-profit research institute located in Washington D.C. 24.457561
872513 Earth Policy Institute Earth Policy Institute was an independent non-profit environmental organization based in Washington, D.C. 22.730673
895248 Arab American Institute Founded in 1985, the Arab American Institute is a non-profit membership organization based in Washington D.C. 21.955559
1950599 Environmental Law Institute The Environmental Law Institute (ELI) is a non-profit, non-partisan organization, headquartered in Washington, D.C. 21.231567
2351478 Public Knowledge Public Knowledge is a non-profit Washington, D.C. 20.742344

# 利用自然语言查询

MyScale 使用 Tantivy 库进行全文搜索(FTS)索引,支持复杂的自然语言查询。有关详细信息,请参阅 官方文档 (opens new window)

下面是一个使用 ANDOR 进行多条件组合查询的示例。我们想要搜索与纽约市、非洲或巴黎相关的人类学主题。SQL 查询如下:

SELECT
    id,
    title,
    body,
    TextSearch(body, 'Anthropological AND ("New York City" OR African OR Paris)') AS score
FROM default.en_wiki_abstract
ORDER BY score DESC
LIMIT 5;

搜索结果显示,每行文本都包含单词 "Anthropological"(不区分大小写),满足 AND 语句左侧的条件。同时,每个结果至少包含 "New York City"、"African" 或 "Paris" 中的一个,满足 AND 语句右侧的匹配条件。

id title body score
2826913 African Anthropologist African Anthropologist is the journal of the Pan African Anthropological Association (PAAA). 20.131313
3905943 Tunnel People Tunnel People is an anthropological-journalistic account describing an underground homeless community in New York City. It is written by war photographer and anthropologist Teun Voeten and was published by PM Press in 2010. 13.759308
3790627 Les Accords de Bella Les Accords de Bella is a 2007 anthropological documentary film directed by David Constantin. It was selected by the African Film Festival of Cordoba - FCAT. 12.769518
4488199 Naparay Naparay, in African anthropological study, is a non-linear conception of human life held by some West African peoples such as the Yoruba. Similar to reincarnation, naparay holds that lives are cyclic and attributes of previous lives may carry over to a new life. 11.682068
1725559 Gradhiva Gradhiva is an anthropological and museological journal, founded in 1986 by the poet and social scientist Michel Leiris and by the anthropologist Jean Jamin. It is since 2005 published by the Musée du Quai Branly in Paris. 11.135916

# 利用 SkipIndex 进行字符串搜索

当使用以下 ClickHouse 内置函数进行字符串搜索时,它们都将通过 FTS 索引进行过滤:equalsnotEqualslikenotLikehasTokenhasTokenOrNullinnotInstartsWithendsWithhasmapContainsmultiSearchAny

示例 1:执行简单的关键字搜索,例如搜索单词 'Tsinghua'。

SELECT count(*)
FROM default.en_wiki_abstract
WHERE hasToken(body, 'Tsinghua');

输出:

count()
81

示例 2:执行多关键字搜索,查找包含 Eiffel Tower 但不包含 Paris 的文章。

SELECT count(*)
FROM default.en_wiki_abstract
WHERE (NOT hasToken(body, 'Paris')) AND multiSearchAny(body, ['Eiffel', 'Tower'])

输出:

count()
2828

示例 3:执行复杂的条件组合查询,结合不同的名称、地点、学科和其他术语。

SELECT count(*)
FROM default.en_wiki_abstract
WHERE (NOT multiSearchAny(body, ['Montessori', 'postulated', 'Rooney'])) AND (hasToken(body, 'Patsy') OR hasToken(body, 'Anthropological'))

输出:

count()
204

# 结论

本指南介绍了如何利用 MyScale 进行高级文本搜索功能,从设置 FTS 索引到执行自然语言查询。通过应用这些技术,您可以高效地管理和搜索非结构化文本数据,展示了 MyScale 强大的文本处理能力。

Last Updated: Mon Apr 29 2024 08:06:28 GMT+0000