2015-07-03 2 views
2

Я разрабатываю postgreSQL-запрос, чтобы использовать возможности нечеткого поиска при поиске имени компании в приложении, над которым я работаю. Я нашел и работал с методом Postgres «Levenshtein» (часть модуля fuzzystrmatch) и по большей части работает. Однако, похоже, это работает только тогда, когда имя компании является одним словом, например:PostgreSQL Fuzzy Поиск нескольких слов с Levenshtein

С Apple (который хранится в базе данных как простое яблоко) я могу запустить следующий запрос и заставить его работать идеально (он возвращает Левенштейна 0):

SELECT * FROM contents 
    WHERE levenshtein(company_name, 'apple') < 4; 

Однако, когда я беру тот же подход, с Sony (который хранится в базе данных как 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; 

Так что мой вопрос заключается в следующем: есть ли какой-то способ, что Я могу точно реализовать многословный нечеткий поиск с текущим общим подходом, который у меня есть сейчас, или я смотрю в совершенно неправильное место?

Спасибо!

ответ

0

Учитывая ваши данные и следующий запрос с дикими значениями для Левенштейн вставки (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 INSER Тион и 2 изменяет
  • Row 4 - 1 удаление и 4 изменяет
  • Строка 5 - 3 изменения

Я обнаружил, что разделив эти слова вызывает много ложных срабатываний Whe вы даете порог. Вы можете заказать расстояние Левенштейна, чтобы расположить лучшие матчи близко к вершине. Возможно, настройка переменных Levenshtein поможет вам лучше заказать матчи. К сожалению, Левенштейн не взвешивает более ранние изменения иначе, чем последующие изменения.

Смежные вопросы