使用PostgreSQL创建高级搜索引擎

​本文我们将探索PostgreSQL中的全文搜索功能,并研究我们能够复制多少典型搜索引擎功能。

如果您想跟随并尝试示例查询(我们建议这样做,这样更有趣),可以使用来自Kaggle的Wikipedia电影情节数据集执行代码示例。要导入它,请下载CSV文件,然后创建以下表格:

CREATE TABLE movies(  ReleaseYear int,  Title text,  Origin text,  Director text,  Casting text,  Genre text,  WikiPage text,  Plot text);

并像这样导入 CSV 文件:

\COPY movies(ReleaseYear, Title, Origin, Director, Casting, Genre, WikiPage, Plot)  FROM 'wiki_movie_plots_deduped.csv' DELIMITER ',' CSV HEADER;

该数据集包含 34,000 个电影标题,CSV 格式大小约为 81 MB。

PostgreSQL全文搜索原语 

PostgreSQL的全文搜索方法提供了一些基础组件,您可以将它们组合起来创建自己的搜索引擎。这种方法非常灵活,但也意味着与Elasticsearch、Typesense或Mellisearch等搜索引擎相比,它通常感觉更低级,因为全文搜索并非主要用例。

主要的基础组件,我们将通过示例进行介绍,包括:

  • tsvector和tsquery数据类型 

  • match运算符@@,用于检查tsquery是否与tsvector匹配 

  • 用于对每个匹配进行排名的函数(ts_rank、ts_rank_cd) 

  • GIN索引类型,用于高效查询tsvector的倒排索引 

我们将从这些基础组件开始,然后深入研究更高级的主题,包括相关性提升、容错处理和分面搜索。

tsvector 

tsvector数据类型存储了一个排序后的词元列表。词元是一个字符串,就像一个标记,但它已被规范化,以便生成不同形式的同一个词。例如,规范化通常包括将大写字母转换为小写字母,并经常涉及去除后缀(例如英语中的s或ing)。下面是一个示例,使用to_tsvector函数将一个英语短语解析为tsvector。

SELECT * FROM unnest(to_tsvector('english',  'I''m going to make him an offer he can''t refuse. Refusing is not an option.')); lexeme | positions | weights--------+-----------+--------- go     | {3}       | {D} m      | {2}       | {D} make   | {5}       | {D} offer  | {8}       | {D} option | {17}      | {D} refus  | {12,13}   | {D,D}(6 rows)

正如您所见,停用词(例如"I"、"to"或"an")被移除,因为它们在搜索中没有太大用处。这些词被规范化并缩减到它们的词根形式(例如"refuse"和"Refusing"都被转换为"refus")。标点符号被忽略。对于每个词,记录了它在原始短语中的位置(例如"refus"是文本中的第12和第13个词),以及权重(在后面我们将讨论它们在排名中的用途)。

在上面的示例中,词到词元的转换规则是基于英语搜索配置的。使用简单搜索配置运行相同的查询将导致包含所有单词的tsvector,这些单词与文本中找到的单词一致。

SELECT * FROM unnest(to_tsvector('simple',  'I''m going to make him an offer he can''t refuse. Refusing is not an option.'));  lexeme  | positions | weights----------+-----------+--------- an       | {7,16}    | {D,D} can      | {10}      | {D} going    | {3}       | {D} he       | {9}       | {D} him      | {6}       | {D} i        | {1}       | {D} is       | {14}      | {D} m        | {2}       | {D} make     | {5}       | {D} not      | {15}      | {D} offer    | {8}       | {D} option   | {17}      | {D} refuse   | {12}      | {D} refusing | {13}      | {D} t        | {11}      | {D} to       | {4}       | {D}(16 rows)

正如您所见,"refuse"和"refusing"现在生成了不同的词元。简单配置在包含标签或标记的列中非常有用。

PostgreSQL内置了一套相当不错的语言配置。您可以运行以下命令查看列表:

SELECT cfgname FROM pg_ts_config;

值得注意的是,目前没有适用于CJK(中日韩)语言的配置,如果您需要在这些语言中创建搜索查询,这一点值得记住。虽然简单配置在实践中对不支持的语言应该工作得很好,但我不确定对于CJK语言是否足够。

tsquery tsquery数据类型用于表示规范化的查询。tsquery包含搜索术语,这些术语必须是已经规范化的词元,并且可以使用AND、OR、NOT和FOLLOWED BY等运算符组合多个术语。有一些函数(如to_tsquery、plainto_tsquery和websearch_to_tsquery)可帮助将用户编写的文本转换为正确的tsquery,主要是通过对文本中出现的单词进行规范化。

为了对tsquery有所了解,让我们通过websearch_to_tsquery看几个示例:

SELECT websearch_to_tsquery('english', 'the dark vader');
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值