添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
courses, to_tsvector(courses.title || courses.description) document, to_tsquery('sales') query, NULLIF(ts_rank(to_tsvector(courses.title), query), 0) rank_title, NULLIF(ts_rank(to_tsvector(courses.description), query), 0) rank_description, SIMILARITY('sales', courses.title || courses.description) similarity WHERE query @@ document OR similarity > 0 ORDER BY rank_title, rank_description, similarity DESC NULLS LAST

但是,如果您需要了解上述 SQL 语句到底在做什么,让我向您解释一下 PostgreSQL 中的上下文和 FTS(全文搜索)基础知识。

背景很重要

很多年前,我读过 这篇很棒 的博文,名为“Postgres 全文搜索足够好”。真的很值得一读,我可以得到很多见解,因为我已经使用 PostgreSQL 作为我的标准数据库。

到那时,我已经习惯了使用 ElasticSearch 进行文本搜索(如果我们在此之前回到 2009 年,我就有使用 ElasticSearch 所基于的 Apache Lucene 的经验)。

但是,管理 ElasticSearch 部署 并不容易 。这需要很大的耐心和记忆力🍪。

然后回到 2014 年,我写了 这篇文章 ,解释了我决定尝试 PG 文本搜索的原因,并展示了一个 Ruby 应用程序中的实际示例。

在本指南中,我将重点介绍一个仅使用 SQL 的更简单但功能强大的示例,因此如果您想跟随我一起冒险,请确保您已 安装 PostgreSQL

这是唯一的要求。不再需要安装或设置工具。仅 Postgres。

为了进一步解释文本搜索、相关性和结果排名的基本原理,我们必须在我们的数据库中植入真实数据并比较不同的搜索策略。

让我们创建一个名为 courses 仅包含 a title description 列的表。这些列将是我们的“可搜索”列,我们将在其中执行文本搜索:

CREATE TABLE courses
(id SERIAL PRIMARY KEY, 
title VARCHAR(80) NOT NULL, 
description VARCHAR(200) NOT NULL);
   
INSERT INTO courses (title, description) VALUES
  ('Improve your sales skills', 'A complete course that will help you to improve your sales skills'),
  ('Intro to Computer Science', 'Understant how computers work'),
  ('Law 101', 'Have you ever wondered doing some Law?'),
  ('Natural Sciences the easy way', 'Your guide to understand the world'),
  ('Mathematics: a gentle introduction', 'Numbers are easy'),
  ('The crash course of Data Science', 'Be a data scientist in 5 weeks'),
  ('Sales crash course', 'Yet another course on Sales'),
  ('Java in a nutshell', 'Learn Java in 21 days'),
  ('Ruby programming language', 'DDH sales Ruby, but could you buy it?'),
  ('Sales matter', 'Really?'),
  ('History in 3 pages', 'Can you learn history in 3 pages?'),
  ('Mastering Git', 'Git history will no longer bother you'),
  ('Cooking like a boss', 'Be the next master chef'),
  ('Master Chef 3.0', 'Cooking revisited'),
  ('Functional Programming in a nutshell', 'Learn FP in 4 days');

关于 LIKE/ILIKE 的注意事项

许多系统使用模式匹配功能来实现非常简单的文本搜索。对于许多场景来说这已经足够了,但是平台在要求苛刻的用户中增长得越多,搜索就越需要返回更好的结果,并具有更准确的相关性和排名。

根据Postgres 官方文档,模式匹配LIKE | ILIKE缺少现代系统所需的基本属性:

它们不提供搜索结果的排序(排名),这使得它们在找到数千个匹配文档时无效。

它们往往很慢,因为没有索引支持,因此它们必须为每次搜索处理所有文档。

没有语言支持,即使是英语。正则表达式是不够的,因为它们不能轻易处理派生词......

举一个更实际的例子,由于我们赋予标题更多的相关性而不是描述,让我们在行动中看看ILIKE缺乏这样的要求:

我们希望课程 10(其标题中包含单词“Sales”)出现在课程 9 之前,课程 9 的描述中包含该单词。

此外,我们的订购标准是什么?如何按“分数”排序,这样我们就可以建立我们的结果排名?

全文搜索救援

PostgreSQL 中的全文搜索

全文搜索(FTS) 允许对文档进行预处理并保存索引以供以后快速搜索和排名。请参阅官方文档,该文档非常完整,提供了理解和实施 FTS 所需的所有信息。

PG(Postgres)中 FTS 的主要构建块是:

  • tsvector,它代表一个可搜索的文档
  • tsquery,这是针对文档执行的搜索查询

to_tsvector函数解析输入文本并将其转换为表示可搜索文档的搜索类型。例如:

  • 结果是准备被搜索的词位列表
  • 停用词(“in”、“a”、“the”等)被删除
  • 数字是文档中词位的位置:java:1从第 1 个位置开始,而nutshell:4从第 4 个位置开始

to_tsquery函数解析输入文本并将其转换为表示查询的搜索类型。例如,用户想要搜索“java in a nutshell”:

/* 0.06079271 */
SELECT ts_rank(to_tsvector('Java in a nutshell'), to_tsquery('nutshell')) 
/* 0 */
SELECT ts_rank(to_tsvector('Java in a nutshell'), to_tsquery('batatas'))

伟大的!现在,我们拥有了实现更好的文本搜索所需的一切,并对我们的课程进行适当的排名。

搜索具有排名的课程

排名结果意味着我们必须将文档拆分为不同的排名,以便我们可以相应地执行排序

我们基本上需要导出排名字段:

ts_rank(to_tsvector(courses.title), query) as rank_title, ts_rank(to_tsvector(courses.description), query) as rank_description to_tsvector(courses.title || courses.description) document, to_tsquery('sales') query WHERE query @@ document courses.title, courses.description, ts_rank(to_tsvector(courses.title), query) as rank_title, ts_rank(to_tsvector(courses.description), query) as rank_description courses, to_tsvector(courses.title || courses.description) document, to_tsquery('sales') query WHERE query @@ document ORDER BY rank_description, rank_title DESC

创建适当的索引(文本搜索的 GIN 索引),可以将性能提高几个数量级。

在这个项目中,我做了一个概念验证,可以在几毫秒内搜索 1200 万个城市。仅 GIN 索引。不需要物化视图。

让我们看看如何为我们的课程表创建 GIN 索引:

只需坐下来,放松并享受搜索数百万门课程的乐趣,而不会出现性能问题。

模糊搜索呢?

模糊搜索或“字符串近似匹配”是用于计算两个字符串的近似值的技术。它通常用于预测查询中的拼写错误等。

遗憾的是,Postgres 内置的 FTS 不支持模糊搜索,但是,通过使用扩展,我们可以将全文搜索和模糊搜索结合在同一个 SQL 查询中。

让我们创建扩展:

请注意,针对文本“Java in a nutshell”搜索“jova”,全文搜索匹配运算符返回 false,而扩展SIMILARITY提供的函数pg_trgm返回 value 0.09

在从 0 到 1 的范围内,相似的字符串往往接近 1。

所以这里我们用16 行 SQL 代码在 PostgreSQL 中实现了一个带有排名和模糊搜索的全文搜索:

courses, to_tsvector(courses.title || courses.description) document, to_tsquery('curse') query, NULLIF(ts_rank(to_tsvector(courses.title), query), 0) rank_title, NULLIF(ts_rank(to_tsvector(courses.description), query), 0) rank_description, SIMILARITY('curse', courses.title || courses.description) similarity WHERE query @@ document OR similarity > 0 ORDER BY rank_title, rank_description, similarity DESC NULLS LAST
  • 我们对标题和描述应用相似度函数
  • 当搜索没有匹配时,我们过滤相似度大于0的结果
  • 添加了NULLIF函数,因此当rank_*为 0 时,我们将值转换为,NULL以便排序可以将 NULL 值视为排名结果中的最后一个

本指南非常繁重,但仅涵盖了 Postgres 中全文搜索的基础知识。在官方文档中,您可以看到更多的特性和功能,例如高亮文档、权重、查询树、查询重写、字典、触发器等。

它可靠且快速,这意味着它可以用于广泛的需求,从简单的搜索系统到复杂的搜索系统。如果您的堆栈中已经有 PostgreSQL,则值得考虑在使用外部/昂贵的替代方案之前对其进行试验,这需要更多地关注操作复杂性。

我希望你能享受在 PostgreSQL 中实现 FTS 的过程。搜索愉快!

A powerful full-text search in PostgreSQL in less than 20 lines

这篇博文将引导您了解使用PostgreSQL实现足够好的全文搜索所需的基本部分。剧透警告:对于那些寻找“好的,只需向我展示一个全文搜索,在 Postgres 中不到 20 行的排名和模糊搜索”的好奇的人,所以你去:SELECT courses.id, courses.title, courses.description, rank_title, rank_description, similarityFROM courses, . pg_similarity是对支持相似性查询的扩展。 就实现而言,该实现紧密地集成在RDBMS,因为它定义了运算符,因此可以使用~~~代替传统的运算符(=和<>)。 ! (这些运算符的任何一个都代表相似性函数)。 pg_similarity具有三个主要组成部分: 函数:实现文献可用的相似性算法的一组函数。 这些函数可以用作UDF,并且将是实现相似性运算符的基础; 运算符:在相似度函数顶部定义的一组运算符。 他们使用相似性函数来获取相似性阈值,并将其值与用户定义的阈值进行比较,以判断其是否匹配; 会话变量:一组存储相似性函数参数的变量。 这些变量可以在运行时定义。 PostgreSQL所支持上都支持pg_similarity 。 安装步骤取决于您的操作系统。 您还可以掌握克隆Git存储库的最新修补程序和功能。 $ git clone https://github
PostgreSQL全文检索tsvectortsquery PostgreSQL全文检索 在日常的数据处理,我们经常会有这样的需求:从一个文本寻找某个字符串(比如某个单词)。 对这个需求,我们可以用类似这样的SQL完成: SELECT * FROM student WHERE text LIKE ‘%pgsql%’; (找到含有“pgsql”的文本)。 现在我们考虑一些特殊的情形: 需要查找的文本特别多,特别大; 不做单纯的字符串匹配,而是考虑自然语言的一些特性,比如匹配某一类字符串(域名、人名).
文章目录一、分子指纹计算二、相似性搜索三、自定义搜索函数 一、分子指纹计算 本文介绍在windows环境下,使用rdkit函数在postgresql数据库进行相似性搜索。环境搭建、数据表准备不再赘述,可以参考这篇文章。在上述工作基础上,继续进行指纹计算、建立索引。操作之前先看看在postgresql支持的指纹函数: layered_fp(mol):另一种rdkit原创指纹,官方文档的解释是它一种子结构指纹,与rdkit拓扑子图的生成步骤一致,但根据子图生成指纹向量的过程有所不同。在子结构指纹类别,l
6.x 7.x 的区别十分大,6.x API (原生API、RestFul 高级!) Lucene 是一套信息检索工具包!jar包!,不包含搜索引擎系统!包含:索引结构、读写索引的工具、排序、搜索规则...工具类。 Lucene 和 ElasticSearch 关系 ElasticSearch 是基于Lucene 做了一些封装和增强(我们上手是十分简单!) ElasticSearch概述 ElasticSearch,简称为es,es是一个开源的高扩展 使用Django和PostgreSQL轻松进行全文搜索。 Sane默认设置+自动创建矢量字段,索引和数据库触发器。 使用SearchableModel类扩展模型,并使用SearchableTextField类自动设置全文搜索: from django . db . models import TextField from django_searchable . models import SearchableModel , SearchableTextField class Blog ( SearchableModel ): author_name = TextField () # will NOT have FTS setup automatically title = SearchableTextField () # will have F
目录安装postgresql13数据库全文检索从表查询字段 需求:使用postgresql13版本测试全文检索功能 安装postgresql13数据库 我这里是使用的docker容器安装测试的 1、创建一个centos7镜像容器 docker run -di --name postgres13 --privileged=true -p 5432:5432 centos:7 /usr/sbin/init docker exec -it postgres13 bash 2、编辑数据库yum安装源
阅读原文:http://click.aliyun.com/m/22329/ 摘要: 标签 PostgreSQL , 文本相似 , pg_similarity , pg_trgm , rum , fuzzymatch gin , smlar 背景 文本相似算法,结合PostgreSQL的开放索引框架GIN,可以实现各种相似算法的文本高效检索。 PostgreSQL , 文本相似 ...
URL:https://www.digitalocean.com/community/tutorials/how-to-use-full-text-search-in-postgresql-on-ubuntu-16-04#step-1-%E2%80%94-creating-example-data DESC:Postgresql全文索引 Last Update:20
Spring Boot 3.0 Security 6定制UserDetailsService,动态权限,Thymeleaf,密码强度、过期、锁定、解锁、禁用、历史新密码编辑距离、登录日志、Envers lincmee: springboot3 不是jdk17 以上吗表情包