欧酷网

您的位置:主页>数据库>

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 1bill=# 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)
  • 点赞

  • 收藏

  • 分享

  •    
    • 文章举报

foucus、

 
发布了97 篇原创文章 ·    获赞 25 ·    访问量 9266  

私信

关注

相关文章推荐