PostgreSQL使用Levenshtein模糊搜索多个单词

4
我正在编写一个PostgreSQL查询,以便在我正在开发的应用程序中搜索公司名称时具有模糊搜索功能。我已经找到并使用了Postgres的Levenshtein方法(属于fuzzystrmatch模块),在大多数情况下它是有效的。但是,只有当公司名称为一个单词时才能正常工作,例如:
对于苹果(在数据库中仅存储为apple),我可以运行以下查询,并且它几乎完美地工作(返回Levenshtein距离为0):
SELECT * FROM contents 
  WHERE levenshtein(company_name, 'apple') < 4;

然而,当我用相同的方法处理索尼(在数据库中存储为Sony Electronics INC)时,无法得到任何有用的结果(输入“Sony”会得到一个16的莱文斯坦距离)。

我尝试通过将公司名称拆分为单独的单词,并逐个输入每个单词来解决此问题,得到了如下结果:

user input => 'sony'

SELECT * FROM contents 
  WHERE levenshtein('Sony', 'sony') < 4 
  OR levenshtein('Electronics', 'sony') < 4 
  OR levenshtein('INC', 'sony') < 4;

我的问题是:我现在的通用方法是否可以准确实现多词模糊搜索,或者我正在完全错误的地方寻找答案?

谢谢!

1个回答

3

考虑到你的数据以及以下带有Levenshtein插入(10000)、删除(100)和替换(1)代价的通配符查询:

with sample_data as (select 101 "id", 'Sony Entertainment Inc' as "name"
                      union
                     select 102 "id",'Apple Corp' as "name")
select sample_data.id,sample_data.name, components.part,
       levenshtein(components.part,'sony',10000,100,1) ld_sony
from sample_data
inner join (select sd.id,
                   lower(unnest(regexp_split_to_array(sd.name,E'\\s+'))) part
            from sample_data sd) components on components.id = sample_data.id

输出如下:
 id  |          name          |     part      | ld_sony 
-----+------------------------+---------------+---------
 101 | Sony Entertainment Inc | sony          |       0
 101 | Sony Entertainment Inc | entertainment |     903
 101 | Sony Entertainment Inc | inc           |   10002
 102 | Apple Corp             | apple         |     104
 102 | Apple Corp             | corp          |       3
(5 rows)
  • 第1行 - 无更改
  • 第2行 - 9处删除和3处更改
  • 第3行 - 1处插入和2处修改
  • 第4行 - 1处删除和4处修改
  • 第5行 - 3处修改

我发现将单词拆分出来会导致在设定阈值时出现许多错误的匹配。您可以按Levenshtein距离排序,以将更好的匹配项放置在靠近顶部的位置。也许调整Levenshtein变量可以帮助您更好地排序匹配项。不幸的是,Levenshtein没有对较早的更改和较晚的更改进行加权。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接