在PostgreSQL中实现按拼音、汉字、拼音首字母搜索的例子

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介:

在PostgreSQL中实现按拼音、汉字、拼音首字母搜索的例子

作者

digoal

日期

2016-11-09

标签

PostgreSQL , 拼音 , 中文分词 , tsvector , 拼音首字母 , hmm , 词库


背景

PostgreSQL有很多特性是可以提升开发效率,提高生产力的。

在前端页面中,搜索是一个非常常用的功能,例如淘宝首页的搜索。

pic1

为了提升用户体验,用户可以按拼音首字母进行搜索,按中文单词搜索,或者按拼音的全部进行搜索。

又比如家里的电视盒子,因为没有实体键盘,按拼音首字母搜索就非常方便。

但是如何做到按拼音首字母或者按拼音可以进行匹配呢?

应用程序端转换

本文的CASE主要需要用到的是中文和拼音以及拼音首字母的相互转换。

例如这样的转换

夹克
jk
jiake

大闹天宫
dntg
danaotiangong

有一个很好的例子

http://www.letiantian.me/2016-02-08-pinyin-hanzi/

基于词库的汉字转拼音

词库中既要包含每个字的拼音,也要包含常用单词/短语的读音。有些字是多音字,所以至少要保存其最常用的读音,不常用的读音多出现在单词/短语里。

好了,词库准备好了,现在手头有一句话要转换要转换为拼音,这句话是:

你好世界杯

我们的词库是这样子的:

你:nǐ
好:hǎo,hào
世:shì
界:jiè
杯:bēi
世界:shì,jiè
你好:nǐ,hǎo
苦尽甘来:kǔ,jìn,gān,lái

词库中最长的词 苦尽甘来 包含4个字。所以 你好世界杯 从4个字开始匹配:

  • 判断你好世界是否在词库中,不在;
  • 判断你好世是否在词库中,不在;
  • 判断你好是否在词库中,在,得到nǐ,hǎo;
  • 判断世界杯是否在词库中,不在;
  • 判断世界是否在词库中,在,得到shì,jiè;
  • 判断杯是否在词库中,在,得到bēi;

于是你好世界杯被转换为nǐ,hǎo,shì,jiè,bēi。

基于词库和分词工具的汉字转拼音

纯粹的基于词库的方法在实际的使用中会遇到问题,例如 提出了解决方案 这句话中 了解 会被当作一个单词,所以会得到错误的结果:

tí,chū,liǎo,jiě,jué,fāng,àn

更好的方法是先进行分词得到:

提出
了
解决
方案

然后基于词库对每个结果分别处理。

基于HMM的拼音转汉字

这里的拼音一般不带声调。

将汉字作为隐藏状态,拼音作为观测值,使用viterbi算法可以将多个拼音转换成合理的汉字。例如给出 ti,chu,le,jie,jue,fang,an ,viterbi算法会认为 提出了解决方案 是最合理的状态序列。

HMM需要三个分布,分别是:

  • 初始时各个状态的概率分布
  • 各个状态互相转换的概率分布
  • 状态到观测值的概率分布

这个3个分布就是三个矩阵,根据一些文本库统计出来即可。

viterbi算法基于动态规划,维基百科 - Viterbi algorithm给出了很好的解释和示例。

基于词库的拼音转汉字

原则:

  • 词的权重大于字的权重;

转换中匹配的词越多,权重越小。

词库的格式是:

拼音:单词:权重

例如:

ni:你:0.15
ni:泥:0.12
a:啊:0.18
hao:好:0.14
nihao:你好:0.6

假如输入是 ni,hao,a ,我们计算一下各种组合的权重:

组合 权重
你,好,啊 0.15×0.14×0.18 = 0.00378
泥,好,啊 0.12×0.14×0.18 = 0.003024
你好,啊 0.6×0.18 = 0.108

可以看出,你好,啊 是最好的结果。

实际实现中需要用到动态规划, 和求有向无环图中两点之间最短距离类似。

代码实现

基于上面的思路,我编写了两个工具,欢迎指教 ^^

拼音转汉字(拼音输入法引擎):https://github.com/letiantian/Pinyin2Hanzi

汉字转拼音:https://github.com/letiantian/ChineseTone

参考

https://github.com/jmz331/gpinyin

http://www.letiantian.me/2016-02-08-pinyin-hanzi/

https://github.com/letiantian/Pinyin2Hanzi

https://github.com/letiantian/ChineseTone

http://www.pudn.com/downloads370/sourcecode/windows/ime/detail1600247.html

数据库端转换

可以把相关的中文,拼音相互转换的代码,嫁接到PostgreSQL,作为UDF对外提供转换接口。

例如输入 zh_to_pinyin('你好') 返回 nihao,nh

或者可以结合中文分词一起使用,同时支持自定义delimiter。

例如输入 zh_to_pinyin('你好中国汉字', ';', ',') 返回 nihao,nh;zhongguo,zg;hanzi,hz

PostgreSQL存储例子

1. 首先我们应该考虑分词,例如用户输入一个字符串,返回分词后的word。

例如

to_tsvector('zhparser', '你好中国')

返回

你好,中国

2. 然后对word进行转换,得到转换后的值。

例如输入 zh_to_pinyin(to_tsvector('zhparser', '你好中国')) 返回 你好,中国,nihao,nh,zhongguo,zg

使用PostgreSQL分词插件得到分词的例子《使用阿里云PostgreSQL zhparser时不可不知的几个参数》

https://yq.aliyun.com/articles/7730

postgres=# create extension zhparser;
CREATE EXTENSION
postgres=# CREATE TEXT SEARCH CONFIGURATION testzhcfg (PARSER = zhparser);
CREATE TEXT SEARCH CONFIGURATION
postgres=# ALTER TEXT SEARCH CONFIGURATION testzhcfg ADD MAPPING FOR a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z WITH simple;
ALTER TEXT SEARCH CONFIGURATION
postgres=# set zhparser.punctuation_ignore = t;  -- 忽略标点符号
SET
postgres=# select * from ts_debug('testzhcfg','你好中国');  -- 得到分词后, 转换为拼音和拼音首字母
 alias | description | token | dictionaries | dictionary | lexemes 
-------+-------------+-------+--------------+------------+---------
 n     | noun        | 你好  | {simple}     | simple     | {你好}
 n     | noun        | 中国  | {simple}     | simple     | {中国}
(2 rows)
postgres=# select to_tsvector('testzhcfg', '你好,中国,nihao,nh,zhongguo,zg');  --  现在你有了所有需要的元素, 存入数组或tsvector就看你的喜好了
                      to_tsvector                       
--------------------------------------------------------
 'nh':4 'nihao':3 'zg':6 'zhongguo':5 '中国':2 '你好':1
(1 row)

这些动作可以封装为一个UDF来执行,提升效率,减少交互次数。

3. 得到转换后的值之后,再存入对应的字段中。

在PostgreSQL中,你可以选择存储为字符串数组,或者tsvector类型。

将 你好,中国,nihao,nh,zhongguo,zg 存入  

text[]

或 

tsvector

这两种类型都支持包含的查询。

检索例子

1. 精确匹配

数组
column @> array['nihao']  
postgres=# select array['你好','中国','nihao','nh','zhongguo','zg'] @> array['nh'];
 ?column? 
----------
 t
(1 row)

tsvector
column @@ to_tsquery('nihao')  
postgres=# select to_tsvector('testzhcfg', '你好,中国,nihao,nh,zhongguo,zg') @@ to_tsquery('你好');
 ?column? 
----------
 t
(1 row)
postgres=# select to_tsvector('testzhcfg', '你好,中国,nihao,nh,zhongguo,zg') @@ to_tsquery('nh');
 ?column? 
----------
 t
(1 row)
postgres=# select to_tsvector('testzhcfg', '你好,中国,nihao,nh,zhongguo,zg') @@ to_tsquery('nh | 你哈');
 ?column? 
----------
 t
(1 row)

2. 操作符

数组

pic2

tsvector

pic3

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
12月前
|
负载均衡 监控 关系型数据库
百度搜索:蓝易云【PostgreSQL 主从复制方案】
请注意,上述仅为一种主从复制方案的概述,实际实施时可能需要根据特定环境和需求进行调整。建议参考PostgreSQL官方文档和其他可靠资源获取更详细的指南和说明。
106 1
|
Ubuntu 关系型数据库 数据库
百度搜索:蓝易云【Ubuntu系统安装 PostgreSQL详细教程。】
现在,你已经成功在Ubuntu系统上安装了PostgreSQL,并创建了一个新的数据库和用户。你可以使用所创建的用户凭据连接到数据库并开始使用。记得根据你的具体需求进行进一步的配置和安全性调整。
285 2
|
关系型数据库 分布式数据库 数据库
沉浸式学习PostgreSQL|PolarDB 10: 社交、刑侦等业务, 关系图谱搜索
业务场景1 介绍: 社交、刑侦等业务, 关系图谱搜索 - 营销、分销、流量变现、分佣、引爆流行、裂变式传播、家谱、选课、社交、人才库、刑侦、农产品溯源、药品溯源 图式搜索是PolarDB | PostgreSQL在(包括流计算、全文检索、图式搜索、K-V存储、图像搜索、指纹搜索、空间数据、时序数据、推荐等)诸多特性中的一个。 采用CTE语法,可以很方便的实现图式搜索(N度搜索、最短路径、点、边属性等)。 其中图式搜索中的:层级深度,是否循环,路径,都是可表述的。
247 0
沉浸式学习PostgreSQL|PolarDB 10: 社交、刑侦等业务, 关系图谱搜索
|
关系型数据库 分布式数据库 数据库
沉浸式学习PostgreSQL|PolarDB 8: 电商|短视频|新闻|内容推荐业务(根据用户行为推荐相似内容)、监控预测报警系统(基于相似指标预判告警)、音视图文多媒体相似搜索、人脸|指纹识别|比对 - 向量搜索应用
1、在电商业务中, 用户浏览商品的行为会构成一组用户在某个时间段的特征, 这个特征可以用向量来表达(多维浮点数组), 同时商品、店铺也可以用向量来表达它的特征. 那么为了提升用户的浏览体验(快速找到用户想要购买的商品), 可以根据用户向量在商品和店铺向量中进行相似度匹配搜索. 按相似度来推荐商品和店铺给用户. 2、在短视频业务中, 用户浏览视频的行为, 构成了这个用户在某个时间段的兴趣特征, 这个特征可以用向量来表达(多维浮点数组), 同时短视频也可以用向量来表达它的特征. 那么为了提升用户的观感体验(推荐他想看的视频), 可以在短视频向量中进行与用户特征向量的相似度搜索.
305 0
|
存储 运维 Cloud Native
【实操系列】基于AnalyticDB PostgreSQL数据共享实现企业级跨多业务的敏捷分析
云数据仓库AnalyticDB PostgreSQL 版发布了最新自研的云原生架构实例,实现了跨实例间的数据共享能力。允许进行跨实例间的实时数据共享且无需进行数据迁移,可支持构建安全、高效、灵活的数据分析场景。本文介绍了依托数据共享实现云数仓跨多业务实例的敏捷数据分析方案;
【实操系列】基于AnalyticDB PostgreSQL数据共享实现企业级跨多业务的敏捷分析
|
SQL 存储 Oracle
PostgreSQL 事务隔离级别的实现和多版本并发控制|学习笔记
快速学习 PostgreSQL 事务隔离级别的实现和多版本并发控制
553 0
PostgreSQL 事务隔离级别的实现和多版本并发控制|学习笔记
|
关系型数据库 测试技术 PostgreSQL
postgresql实现影响分析
通过postgresql模仿分析假如城市发布通知,位于街道的人员是否受到了影响
121 0
postgresql实现影响分析
|
弹性计算 资源调度 运维
【实操系列】 AnalyticDB PostgreSQL发布实例计划管理功能,实现资源分时弹性&分时启停
本文将对AnalyticDB PostgreSQL产品的计划任务管理功能以及其背后的实现机制和最佳实践做详细介绍。
【实操系列】 AnalyticDB PostgreSQL发布实例计划管理功能,实现资源分时弹性&分时启停
|
存储 Kubernetes 负载均衡
「在 Kubernetes 上运行 Pgpool-Il」实现 PostgreSQL 查询(读)负载均衡和连接池
「在 Kubernetes 上运行 Pgpool-Il」实现 PostgreSQL 查询(读)负载均衡和连接池
348 0
「在 Kubernetes 上运行 Pgpool-Il」实现 PostgreSQL 查询(读)负载均衡和连接池
|
存储 SQL 关系型数据库
数据库误操作后悔药来了:AnalyticDB PostgreSQL教你实现分布式一致性备份恢复
本文将介绍AnalyticDB PostgreSQL版备份恢复的原理与使用方法。
872 0
数据库误操作后悔药来了:AnalyticDB PostgreSQL教你实现分布式一致性备份恢复

相关产品

  • 云原生数据库 PolarDB
  • 云数据库 RDS PostgreSQL 版
  • 下一篇
    无影云桌面