PostgreSQL全文检索位置匹配

pg中的全文检索功能十分丰富,例如我们想要搜索包含“速度与激情”的文档,但是我们都知道pg中的全文检索实质上是将语句进行切词,然后按照词组进行匹配查询的。所以这就会出现一个问题:我们直接查询包含“速度”&“激情”的文档会导致匹配到包含“速度”和“激情”两个单独词语的文档。

那么碰到这种情况该怎么办呢?pg全文检索中支持位置匹配,例如“速度与激情”这个词,分词后是有位置信息的,我们期望搜到的是“速度”和“激情”之间间隔一个的情况,提高精准度。

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

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

例子:
1、创建测试表

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

2、安装中文分词器pg_scws
下载地址:https://github.com/jaiminpan/pg_scws

bill=# create extension pg_scws;
CREATE EXTENSION

3、写入测试数据

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

4、查看分词结果

bill=# 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)

5、写入更多测试数据

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

6、创建rum索引

bill=# create extension rum;  
CREATE EXTENSION  
bill=# CREATE INDEX rumidx ON ts_test USING rum (ts rum_tsvector_ops);
CREATE INDEX

7、查询
不带位置信息,则返回全部记录。

bill=# explain (analyze,verbose,timing,costs,buffers) select * from ts_test where ts @@ '速度 & 激情'::tsquery;  
                                                        QUERY PLAN                                                         
---------------------------------------------------------------------------------------------------------------------------
 Seq Scan on public.ts_test  (cost=0.00..49537.95 rows=999996 width=270) (actual time=0.025..385.005 rows=1000002 loops=1)
   Output: id, info, ts
   Filter: (ts_test.ts @@ '''速度'' & ''激情'''::tsquery)
   Buffers: shared hit=37038
 Planning Time: 0.303 ms
 Execution Time: 444.955 ms
(6 rows)

带上位置,只匹配了1条记录,也就是我们要的“速度与激情”。

bill=# explain (analyze,verbose,timing,costs,buffers) select * from ts_test where ts @@ '速度 <1> 激情'::tsquery;  
                                                     QUERY PLAN                                                      
---------------------------------------------------------------------------------------------------------------------
 Seq Scan on public.ts_test  (cost=0.00..49537.95 rows=999996 width=270) (actual time=0.014..324.677 rows=1 loops=1)
   Output: id, info, ts
   Filter: (ts_test.ts @@ '''速度'' <-> ''激情'''::tsquery)
   Rows Removed by Filter: 1000001
   Buffers: shared hit=37038
 Planning Time: 0.103 ms
 Execution Time: 324.697 ms
(7 rows)
发布了97 篇原创文章 · 获赞 25 · 访问量 8096

猜你喜欢

转载自blog.csdn.net/weixin_39540651/article/details/104053348
今日推荐