数据库开发者社区 > 正文

PostgreSQL 全文检索之 - 位置匹配 过滤语法 (如 '速度 <1> 激情')

简介:
+关注继续查看

标签

PostgreSQL , 全文检索 , 位置过滤


背景

PostgreSQL 的全文检索功能非常的丰富,除了我们说的开放式的parser,字典。同时还支持ranking算法(内置以及扩展)。

那么实际上在搜索的需求中,还有一类位置过滤的需求,例如“速度与激情”这个词,分词后是有位置信息的,我们期望搜到的是“速度”和“激情”之间间隔一个的情况,提高精准度。

PostgreSQL的搜索距离的语法如下:

select * from tbl where ts @@ '速度 <距离值> 激情'::tsquery;  
  
如  
  
select * from tbl where ts @@ '速度 <1> 激情'::tsquery;  

例子

首先需要一个中文分词器,RDS PG自带,无需下载。

https://github.com/jaiminpan/pg_scws

create extension pg_scws;  

1、创建测试表

postgres=# create table ts_test (id int, info text, ts tsvector);  
CREATE TABLE  

2、写入测试数据

postgres=# insert into ts_test values (1, '激情,创新,坚持,速度-- 北京北方创业出租汽车公司优质服务小花絮', to_tsvector('scwscfg', '激情,创新,坚持,速度-- 北京北方创业出租汽车公司优质服务小花絮'));  
INSERT 0 1  
postgres=# insert into ts_test values (1, '电影速度与激情8的票房破亿', to_tsvector('scwscfg', '电影速度与激情8的票房破亿'));  
INSERT 0 1  

3、查看分词结果,其中分词中已经带上了位置信息。

postgres=# select * from ts_test;  
 id |                              info                               |                                                     ts                                                       
----+-----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------  
  1 | 激情,创新,坚持,速度-- 北京北方创业出租汽车公司优质服务小花絮 | '优质服务':9 '公司':8 '出租汽车':7 '创业':6 '创新':2 '北京':5 '坚持':3 '小花':10 '激情':1 '絮':11 '速度':4  
  1 | 电影速度与激情8的票房破亿                                       | '激情':3 '电影':1 '破':5 '票房':4 '速度':2  
(2 rows)  

3、写入更多干扰数据

postgres=# insert into ts_test select 2, '激情,创新,坚持,速度-- 北京北方创业出租汽车公司优质服务小花絮', to_tsvector('scwscfg', '激情,创新,坚持,速度-- 北京北方创业出租汽车公司优质服务小花絮') from generate_series(1,1000000);  
INSERT 0 1000000  

4、创建一个支持位置搜索的索引插件rum。

https://github.com/postgrespro/rum

postgres=# create extension rum;  
CREATE EXTENSION  

5、创建rum分词索引

postgres=# CREATE INDEX rumidx ON ts_test USING rum (ts rum_tsvector_ops);  
CREATE INDEX  

6、接下来见证奇迹,第一个查询是不带位置搜索的,我们看到匹配了所有记录。

postgres=# explain (analyze,verbose,timing,costs,buffers) select * from ts_test where ts @@ '速度 & 激情'::tsquery;  
                                                             QUERY PLAN                                                               
------------------------------------------------------------------------------------------------------------------------------------  
 Index Scan using rumidx on public.ts_test  (cost=9.60..41.24 rows=25 width=68) (actual time=223.602..456.956 rows=1000002 loops=1)  
   Output: id, info, ts  
   Index Cond: (ts_test.ts @@ '''速度'' & ''激情'''::tsquery)  
   Buffers: shared hit=38132  
 Planning time: 0.226 ms  
 Execution time: 541.545 ms  
(6 rows)  

7、第二个查询是带位置了,只匹配了1条记录,也就是我们要的“速度与激情”。

postgres=# explain (analyze,verbose,timing,costs,buffers) select * from ts_test where ts @@ '速度 <1> 激情'::tsquery;  
                                                          QUERY PLAN                                                            
------------------------------------------------------------------------------------------------------------------------------  
 Index Scan using rumidx on public.ts_test  (cost=9.60..41.24 rows=25 width=68) (actual time=270.675..270.677 rows=1 loops=1)  
   Output: id, info, ts  
   Index Cond: (ts_test.ts @@ '''速度'' <-> ''激情'''::tsquery)  
   Buffers: shared hit=1095  
 Planning time: 0.111 ms  
 Execution time: 273.840 ms  
(6 rows)  

PostgreSQL 分词就是这么好用

带距离  
  
postgres=# select * from ts_test where ts @@ '速度 <1> 激情'::tsquery;  
 id |           info            |                     ts                       
----+---------------------------+--------------------------------------------  
  1 | 电影速度与激情8的票房破亿 | '激情':3 '电影':1 '破':5 '票房':4 '速度':2  
(1 row)  
  
不带距离  
  
postgres=# select * from ts_test where ts @@ '速度 & 激情'::tsquery limit 5;  
 id |                              info                               |                                                     ts                                                       
----+-----------------------------------------------------------------+------------------------------------------------------------------------------------------------------------  
  1 | 激情,创新,坚持,速度-- 北京北方创业出租汽车公司优质服务小花絮 | '优质服务':9 '公司':8 '出租汽车':7 '创业':6 '创新':2 '北京':5 '坚持':3 '小花':10 '激情':1 '絮':11 '速度':4  
  1 | 电影速度与激情8的票房破亿                                       | '激情':3 '电影':1 '破':5 '票房':4 '速度':2  
  2 | 激情,创新,坚持,速度-- 北京北方创业出租汽车公司优质服务小花絮 | '优质服务':9 '公司':8 '出租汽车':7 '创业':6 '创新':2 '北京':5 '坚持':3 '小花':10 '激情':1 '絮':11 '速度':4  
  2 | 激情,创新,坚持,速度-- 北京北方创业出租汽车公司优质服务小花絮 | '优质服务':9 '公司':8 '出租汽车':7 '创业':6 '创新':2 '北京':5 '坚持':3 '小花':10 '激情':1 '絮':11 '速度':4  
  2 | 激情,创新,坚持,速度-- 北京北方创业出租汽车公司优质服务小花絮 | '优质服务':9 '公司':8 '出租汽车':7 '创业':6 '创新':2 '北京':5 '坚持':3 '小花':10 '激情':1 '絮':11 '速度':4  
(5 rows)  

参考

《多流实时聚合 - 记录级实时快照 - JSON聚合与json全文检索的功能应用》

《PostgreSQL - 全文检索内置及自定义ranking算法介绍 与案例》

《用PostgreSQL 做实时高效 搜索引擎 - 全文检索、模糊查询、正则查询、相似查询、ADHOC查询》

《HTAP数据库 PostgreSQL 场景与性能测试之 14 - (OLTP) 字符串搜索 - 全文检索》

《HTAP数据库 PostgreSQL 场景与性能测试之 7 - (OLTP) 全文检索 - 含索引实时写入》

《多国语言字符串的加密、全文检索、模糊查询的支持》

《全文检索 不包含 优化 - 阿里云RDS PostgreSQL最佳实践》

《PostgreSQL 10.0 preview 功能增强 - JSON 内容全文检索》

《PostgreSQL 全文检索加速 快到没有朋友 - RUM索引接口(潘多拉魔盒)》

《PostgreSQL 行级 全文检索》

《PostgreSQL chinese full text search 中文全文检索》

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
PostgreSQL 12 文档: SQL 语法
SQL 命令 这部分包含PostgreSQL支持的SQL命令的参考信息。每条命令的标准符合和兼容的信息可以在相关的参考页中找到。
25 0
PostgreSQL psql的使用,SQL语法,数据类型,递归SQL用法(四)|学习笔记
快速学习3 PostgreSQL psql的使用,SQL语法,数据类型,递归SQL用法(四)
201 0
3 PostgreSQL psql的使用,SQL语法,数据类型,递归SQL用法(三)|学习笔记
快速学习3 PostgreSQL psql的使用,SQL语法,数据类型,递归SQL用法(三)
141 0
PostgreSQL的学习心得和知识总结(二十五)|语法级自上而下完美实现MySQL数据库的 字段默认值的自动插入更新 的实现方案
本人CSDN博主 孤傲小二~阿沐,本文《PostgreSQL的学习心得和知识总结(二十五)|语法级自上而下完美实现MySQL数据库的 字段默认值的自动插入更新 的实现方案》来自于我在CSDN的同名文档
118 0
PostgreSQL 12 preview - CTE 增强,支持用户语法层控制 materialized 优化
标签 PostgreSQL , CTE , materialized , not materialized , push down 背景 PostgreSQL with 语法,能跑非常复杂的SQL逻辑,包括递归,多语句物化计算等。 在12以前的版本中,WITH中的每一个CTE(common table express),都是直接进行物化的,也就是说外层的条件不会推到CTE(物化节点)里
628 0
PostgreSQL 10.1 手册_部分 II. SQL 语言_第 4 章 SQL语法
第 4 章 SQL语法 目录 4.1. 词法结构 4.1.1. 标识符和关键词 4.1.2. 常量 4.1.3. 操作符 4.1.4. 特殊字符 4.1.5. 注释 4.1.6. 操作符优先级 4.
928 0
PostgreSQL 10.1 手册_部分 II. SQL 语言_第 4 章 SQL语法_4.3. 调用函数
4.3. 调用函数 4.3.1. 使用位置记号 4.3.2. 使用命名记号 4.3.3. 使用混合记号 PostgreSQL允许带有命名参数的函数被使用位置或命名记号法调用。命名记号法对于有大量参数的函数特别有用,因为它让参数和实际参数之间的关联更明显和可靠。
1021 0
PostgreSQL 10.1 手册_部分 II. SQL 语言_第 4 章 SQL语法_4.2. 值表达式
4.2. 值表达式 4.2.1. 列引用 4.2.2. 位置参数 4.2.3. 下标 4.2.4. 域选择 4.2.5. 操作符调用 4.2.6. 函数调用 4.2.7. 聚合表达式 4.2.8. 窗口函数调用 4.2.9. 类型转换 4.2.10. 排序规则表达式 4.2.11. 标量子查询 4.2.12. 数组构造器 4.2.13. 行构造器 4.2.14. 表达式计算规则 值表达式被用于各种各样的环境中,例如在SELECT命令的目标列表中、作为INSERT或UPDATE中的新列值或者若干命令中的搜索条件。
1141 0
PostgreSQL 10.1 手册_部分 II. SQL 语言_第 4 章 SQL语法_4.1. 词法结构
4.1. 词法结构 4.1.1. 标识符和关键词 4.1.2. 常量 4.1.3. 操作符 4.1.4. 特殊字符 4.1.5. 注释 4.1.6. 操作符优先级 SQL输入由一个命令序列组成。
1245 0
数据库领域前沿技术分享与交流
热门文章
热门讨论
+关注
德哥
公益是一辈子的事, I am digoal, just do it.
文章
问答
视频
相关电子书
更多
金融级 PostgreSQL监控及优化
立即下载
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
相关镜像