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

简介:
 

标签

PostgreSQL , 全文检索 , ranking


背景

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

《排序算法》这个章节实际上介绍了PostgreSQL的ranking算法。

tsvector将文档分为4层结构:标题、作者、摘要、内容。对这四个层级,用户可以设定对应的weight,用于ranking的计算。同时用户可以设定ranking的修正掩码。

但是只有四个层级,远远不能满足业务需求,那么PostgreSQL实现更多层级,更精细的ranking算法呢?

如何自定义ranking呢?

例如在电商行业中,我们可能存储了每个店铺的标签,每个标签旁边可能是一个系数,这个系数可能是动态调整的。在搜索的时候,商店的某些标签被命中了,可能搜索到了几百万个店铺,但是最后要根据权重算出应该如何排序,并得到其中的1万个店铺。

这种情况,如何精细化排序就体现出来了。

例子1 - tsvector向量

1、店铺标签表:

create table tbl (    
  shop_id int8 primary key,   -- 店铺 ID    
  tags text                   -- 多值类型,标签1:评分1,标签2:评分2,.....       
);    

对tags字段,使用UDF索引,存储标签的数组或tsvector索引。

如果使用tsvector,主要是便于使用PostgreSQL的全文检索的语法,包含、不包含、距离等。

tags例如

国民_足浴:0.99,国民_餐饮:0.1,娱乐_KTV:0.45  

2、标签权值表:

create table tbl_weight (    
  tagid int primary key,   -- 标签ID     
  tagname name,            -- 标签名    
  desc text,               -- 标签描述    
  weight float8            -- 标签权值    
);    
  
create index idx_tbl_weight_1 on tbl_weight (tagname);  

3、文本转标签数组、tsvector的UDF

create or replace function text_to_tsvector(text) returns tsvector as $$    
  select array_to_tsvector(array_agg(substring(id,'(.+):'))) from unnest(regexp_split_to_array($1, ',')) as t(id);    
$$ language sql strict immutable;    
    
postgres=# select text_to_tsvector('abc:1.1,bc:100,c:293');    
 text_to_tsvector     
------------------    
 'abc' 'bc' 'c'    
(1 row)    

创建TSVECTOR表达式索引

create index idx_tbl_1 on tbl using gin (text_to_tsvector(tags));  

4、取出命中标签权值的UDF

postgres=# select substring('bc:1.1,abc:100,c:293','[^,]?abc:([\d\.]+)') ;    
 substring     
-----------    
 100    
(1 row)    
    
postgres=# select substring('abc:1.1,bc:100,c:293','[^,]?abc:([\d\.]+)') ;    
 substring     
-----------    
 1.1    
(1 row)    

未命中则返回NULL

postgres=# select substring('abc:1.1,bc:100,c:293','[^,]?adbc:([\d\.]+)') ;    
 substring     
-----------    
     
(1 row)    
    
postgres=# select substring('abc:1.1,bc:100,c:293','[^,]?adbc:([\d\.]+)') is null;    
 ?column?     
----------    
 t    
(1 row)    

5、全文检索

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

select   

6、精排

计算ranking可能是结合 “命中的标签、评分、标签本身的权值” 根据算法得到一个ranking值。

根据4得到命中标签的评分,根据命中标签从tbl_weight得到对应的权值。

将算法封装到UDF,最后得到RANKING。

ranking算法的UDF函数内容略,请根据业务的需要编写对应算法,伪代码如下。

create or replace function cat_ranking(tsquery) returns float8 as $$  
declare  
    
begin  
  for each x in array (contains_element) loop  
    search hit element's score.  
    search hit element's weight.  
    cat ranking and increment  
  end loop;  
  return res;  
end;  
$$ language plpgsql strict;  

7、

7.1 删除标签与对应的评分:

regexp_replace 函数。

7.2 追加标签与对应的评分:

concat函数。

7.3 修改元素评分:

regexp_replace 函数。

以上都可以使用正则表达式来操作。

例子2 - 多维数组

使用数组来存储标签和权值,实际上在编程上会比使用tsvector更简单。

首先需要介绍一些用到的数组函数

根据元素求位置,根据标签,求它的位置,根据这个位置从score[]得到它的SCORE。  
  
postgres=# select array_position(array[1,2,null,null,2,2,3,1],null);  
 array_position   
----------------  
              3  
(1 row)  
  
postgres=# select array_positions(array[1,2,null,null,2,2,3,1],null);  
 array_positions   
-----------------  
 {3,4}  
(1 row)  
  
postgres=# select array_positions(array[1,2,null,null,2,2,3,1],2);  
 array_positions   
-----------------  
 {2,5,6}  
(1 row)  
  
求某个位置的元素  
  
array[i]  
  
postgres=# select (array[1,2,null,null,2,2,3,1])[1];  
 array   
-------  
     1  
(1 row)  
  
postgres=# select (array[1,2,null,null,2,2,3,1])[3];  
 array   
-------  
        
(1 row)  
  
postgres=# select (array[1,2,null,null,2,2,3,1])[5];  
 array   
-------  
     2  
(1 row)  
  
追加元素  
  
array_append  
  
替换元素  
  
array_replace  
  
删除某个元素  
  
array_remove,注意如果有一样的元素,都会被删掉(如果有一样的score,就的注意,需要用删除位置来删除元素)  
  
postgres=# select array_remove(array[1,2,null,null,2,2,3,1],2);  
   array_remove      
-------------------  
 {1,NULL,NULL,3,1}  
(1 row)  
  
删除某个位置的元素,  
  
postgres=# create or replace function array_remove(anyarray,int[]) returns anyarray as $$  
  select array(select $1[i] from (select id from generate_series(1,array_length($1,1)) t(id) where id <> all( $2) ) t(i))  
$$ language sql strict;  
CREATE FUNCTION  
postgres=# select array_remove(array[1,2,null,null,2,2,3,1],array[1,2]);  
    array_remove       
---------------------  
 {NULL,NULL,2,2,3,1}  
(1 row)  
  
postgres=# select array_remove(array[1,2,null,null,2,2,3,1],array[3,5]);  
   array_remove     
------------------  
 {1,2,NULL,2,3,1}  
(1 row)  

1、店铺标签表:

create table tbl (    
  shop_id int8 primary key,   -- 店铺 ID    
  tags text[],                -- 数组,标签1,标签2,.....       
  scores float8[]             -- 数组,评分1,评分2,.....  
);     
  
create index idx_tbl_1 on tbl using gin(tags);  
国民_足浴,国民_餐饮,娱乐_KTV  
  
0.99,0.1,0.45  

2、标签权值表:

create table tbl_weight (    
  tagid int primary key,   -- 标签ID     
  tagname name,            -- 标签名     
  desc text,               -- 标签描述    
  weight float8            -- 标签权值    
);    
  
create index idx_tbl_weight_1 on tbl_weight (tagname);  

3、包含、不包含、相交的数组查询。

https://www.postgresql.org/docs/10/static/functions-array.html

4、精排算法,与例子1类似。自定义UDF即可。

使用array简化了开发工作量,不需要使用正则表达式,效率也会提高。

参考

https://www.postgresql.org/docs/10/static/functions-matching.html

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
数据采集 机器学习/深度学习 算法
|
10月前
|
人工智能 编解码 算法
DeepSeek加持的通义灵码2.0 AI程序员实战案例:助力嵌入式开发中的算法生成革新
本文介绍了通义灵码2.0 AI程序员在嵌入式开发中的实战应用。通过安装VS Code插件并登录阿里云账号,用户可切换至DeepSeek V3模型,利用其强大的代码生成能力。实战案例中,AI程序员根据自然语言描述快速生成了C语言的base64编解码算法,包括源代码、头文件、测试代码和CMake编译脚本。即使在编译错误和需求迭代的情况下,AI程序员也能迅速分析问题并修复代码,最终成功实现功能。作者认为,通义灵码2.0显著提升了开发效率,打破了编程语言限制,是AI编程从辅助工具向工程级协同开发转变的重要标志,值得开发者广泛使用。
8843 71
DeepSeek加持的通义灵码2.0 AI程序员实战案例:助力嵌入式开发中的算法生成革新
|
搜索推荐 前端开发 数据可视化
【优秀python web毕设案例】基于协同过滤算法的酒店推荐系统,django框架+bootstrap前端+echarts可视化,有后台有爬虫
本文介绍了一个基于Django框架、协同过滤算法、ECharts数据可视化以及Bootstrap前端技术的酒店推荐系统,该系统通过用户行为分析和推荐算法优化,提供个性化的酒店推荐和直观的数据展示,以提升用户体验。
731 1
【优秀python web毕设案例】基于协同过滤算法的酒店推荐系统,django框架+bootstrap前端+echarts可视化,有后台有爬虫
|
数据采集 机器学习/深度学习 算法
【优秀设计案例】基于K-Means聚类算法的球员数据聚类分析设计与实现
本文通过K-Means聚类算法对NBA球员数据进行聚类分析,旨在揭示球员间的相似性和差异性,为球队管理、战术决策和球员评估提供数据支持,并通过特征工程和结果可视化深入理解球员表现和潜力。
675 1
【优秀设计案例】基于K-Means聚类算法的球员数据聚类分析设计与实现
|
存储 分布式计算 算法
大数据-106 Spark Graph X 计算学习 案例:1图的基本计算、2连通图算法、3寻找相同的用户
大数据-106 Spark Graph X 计算学习 案例:1图的基本计算、2连通图算法、3寻找相同的用户
262 0
|
机器学习/深度学习 算法 PyTorch
【从零开始学习深度学习】38. Pytorch实战案例:梯度下降、随机梯度下降、小批量随机梯度下降3种优化算法对比【含数据集与源码】
【从零开始学习深度学习】38. Pytorch实战案例:梯度下降、随机梯度下降、小批量随机梯度下降3种优化算法对比【含数据集与源码】
|
存储 算法 搜索推荐
这些算法在实际应用中有哪些具体案例呢
【10月更文挑战第19天】这些算法在实际应用中有哪些具体案例呢
351 1
|
算法 数据可视化 新制造
Threejs路径规划_基于A*算法案例完整版
这篇文章详细介绍了如何在Three.js中完整实现基于A*算法的路径规划案例,包括网格构建、路径寻找算法的实现以及路径可视化展示等方面的内容。
499 0
Threejs路径规划_基于A*算法案例完整版
|
存储 算法 机器人
Threejs路径规划_基于A*算法案例V2
这篇文章详细介绍了如何在Three.js中使用A*算法进行高效的路径规划,并通过三维物理电路的实例演示了路径计算和优化的过程。
476 0
|
机器学习/深度学习 人工智能 算法
【人工智能】传统语音识别算法概述,应用场景,项目实践及案例分析,附带代码示例
传统语音识别算法是将语音信号转化为文本形式的技术,它主要基于模式识别理论和数学统计学方法。以下是传统语音识别算法的基本概述
1095 2

相关产品

  • 云原生数据库 PolarDB
  • 云数据库 RDS PostgreSQL 版
  • 推荐镜像

    更多