PostgreSQL 中 similarity 进行更加智能的模糊搜索

80 阅读2分钟

在数据查询时如果用到模糊搜索,那么一般情况下都是使用 like语句。而这也是模糊查询最简单的方式,它是通过子串的完全匹配来实现的。比如:

Select * from exmaple where name like 'zhang%';

上面的这个语句就会查询出所有以zhang开头的名称,比如: zhang san,zhang liu等。

但这有一个问题,就是如果用户输入了一个zhng或者zhag,那么查询的结果当中就不会匹配到zhang san,zhangliu这些以zhang开头的名称了,而使用similarity就能解决这个问题,带来更好的用户体验

介绍

similarity是 PostgreSQL 中 pg_trgm 扩展的一个函数。它的主要作用就是对任意给定的两个字符串,根据他们之间的相似性,返回一个 0-1 之间的数值,0:表示完全不同,1:表示完全相同;比如:

SELECT similarity('hello', 'hello world');
# 返回结果: 0.5

那现在就可以使用这个函数解决上面碰到的问题了;具体如下:

select name FROM exmaple ORDER BY similarity(name, 'zhag') desc LIMIT 2;

# 输出结果
zhang san
zhang liu

这样就不需要子串的完全匹配才能输出结果,这也大大提升了用户的体验。

注:similarity是 pg_trgm 的一个函数,所以要先添加这个扩展到 postgresql 中,语句如下:CREATE EXTENSION IF NOT EXISTS pg_trgm;

原理

显然,相比于 like,它的智能程度更高,那它是如何实现的呢;下面对其的原理进行简单的说明。

PostgreSQL 中的 similarity 函数是基于三种字符串相似度算法:

  1. Levenshtein 距离: 测量将一个字符串转换成另一个字符串所需的最少单字符编辑操作(插入、删除或替换)的数量。距离越小,字符串越相似。
  2. 最长公共子序列 (LCS): 找出两个字符串中最长的公共子序列的长度。子序列越长,字符串越相似。
  3. q-gram: 将字符串分解成固定长度(q)的重叠子串,然后比较两个字符串共有的 q-gram 数量。共有 q-gram 越多,字符串越相似。

PostgreSQL 的 similarity 函数综合使用了这些算法,根据字符串的长度和特征选择最合适的方法或组合方法来计算相似度。函数返回一个 0 到 1 之间的值,1 表示完全相同,0 表示完全不同。

结语

相比于 likesimilarity提供了更加智能的匹配;并且能够应用到更多的场景当中,比如:搜索建议,重复数据检查等