PostgreSQL 使用 Levenshtein 模糊搜索多个单词
PostgreSQL Fuzzy Searching multiple words with Levenshtein
我正在制定一个 postgreSQL 查询,以便在我正在使用的应用程序中搜索公司名称时允许模糊搜索功能。我已经发现并一直在使用 Postgres 的 Levenshtein 方法(fuzzystrmatch 模块的一部分)并且在大多数情况下它是有效的。但是,它似乎只适用于公司名称是一个单词的情况,例如:
使用 Apple(它在数据库中简单地存储为 apple),我可以 运行 以下查询并使其接近完美地工作(它 returns 编辑距离为 0):
SELECT * FROM contents
WHERE levenshtein(company_name, 'apple') < 4;
然而,当我对索尼采取相同的方法(存储在数据库中作为索尼电子公司)时,我无法获得任何有用的结果(输入索尼给出 levenshtein 距离为 16)。
我试图通过将公司名称分解为单独的单词并单独输入每个单词来解决这个问题,结果如下:
user input => 'sony'
SELECT * FROM contents
WHERE levenshtein('Sony', 'sony') < 4
OR levenshtein('Electronics', 'sony') < 4
OR levenshtein('INC', 'sony') < 4;
所以我的问题是:有没有什么方法可以让我用目前的通用方法准确地实现多词模糊搜索,还是我找错了地方?
谢谢!
给定您的数据和以下查询,其中 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 对早期更改的权重与后期更改的权重不同。
我正在制定一个 postgreSQL 查询,以便在我正在使用的应用程序中搜索公司名称时允许模糊搜索功能。我已经发现并一直在使用 Postgres 的 Levenshtein 方法(fuzzystrmatch 模块的一部分)并且在大多数情况下它是有效的。但是,它似乎只适用于公司名称是一个单词的情况,例如:
使用 Apple(它在数据库中简单地存储为 apple),我可以 运行 以下查询并使其接近完美地工作(它 returns 编辑距离为 0):
SELECT * FROM contents
WHERE levenshtein(company_name, 'apple') < 4;
然而,当我对索尼采取相同的方法(存储在数据库中作为索尼电子公司)时,我无法获得任何有用的结果(输入索尼给出 levenshtein 距离为 16)。
我试图通过将公司名称分解为单独的单词并单独输入每个单词来解决这个问题,结果如下:
user input => 'sony'
SELECT * FROM contents
WHERE levenshtein('Sony', 'sony') < 4
OR levenshtein('Electronics', 'sony') < 4
OR levenshtein('INC', 'sony') < 4;
所以我的问题是:有没有什么方法可以让我用目前的通用方法准确地实现多词模糊搜索,还是我找错了地方?
谢谢!
给定您的数据和以下查询,其中 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 对早期更改的权重与后期更改的权重不同。