Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / PostgreSQL Новый топик    Ответить
 нечеткий поиск  [new]
Troglodit
Member

Откуда:
Сообщений: 498
пытаюсь реализовать нечеткий поиск.
Нашел статью
Пробовал триграммы, но результат неутешительный.
Пробовал использовать кастомный metaphone:
CREATE OR REPLACE FUNCTION test.phoneme(
	in_lexeme text)
    RETURNS text
    LANGUAGE 'plpgsql'

    COST 100
    IMMUTABLE 
    
AS $BODY$
declare
  res varchar(100) DEFAULT '';
begin
  res := lower(in_lexeme);
  res := regexp_replace(res,'[ъь]','','g');
  res := regexp_replace(res,'(йо|ио|йе|ие)','и','g');
  res := regexp_replace(res,'[оыя]','а','g');
  res := regexp_replace(res,'[еёэ]','и','g');
  res := regexp_replace(res,'ю','у','g');
  res := regexp_replace(res,'б([псткбвгджзфхцчшщ]|$)','п\1','g');
  res := regexp_replace(res,'з([псткбвгджзфхцчшщ]|$)','с\1','g');
  res := regexp_replace(res,'д([псткбвгджзфхцчшщ]|$)','т\1','g');
  res := regexp_replace(res,'в([псткбвгджзфхцчшщ]|$)','ф\1','g');
  res := regexp_replace(res,'г([псткбвгджзфхцчшщ]|$)','к\1','g');  
  res := regexp_replace(res,'дс','ц','g');
  res := regexp_replace(res,'тс','ц','g');
  res := regexp_replace(res,'(.)\1','\1','g');
  return res;
exception
  when others then raise exception '%', sqlerrm;
end;
$BODY$;


CREATE OR REPLACE FUNCTION test.metaphone(
	in_phonemes text)
    RETURNS text
    LANGUAGE 'plpgsql'

    COST 100
    IMMUTABLE 
    
AS $BODY$
begin
  return (
    select string_agg(q.lex,' ') from (
      select test.phoneme(lexeme) as lex from unnest(to_tsvector('simple', in_phonemes))	
      order by positions
    ) as q
  );
exception when others then
  raise '%', SQLERRM using errcode = SQLSTATE;
end;
$BODY$;


SELECT 
name,
SIMILARITY(test.metaphone(name),test.metaphone('Ответ на все сущее'))
FROM test.sample
order by 
2 desc
LIMIT 100;

Результат также слабый.
Т.е. даже при изменении порядка следования символов в слове, уже выдает слабый результат.
Если же еще и заменить пару соседних букв,рядом расположенных на клавиатуре, совсем печально.
Может я его как то неправильно готовлю?

Сообщение было отредактировано: 21 янв 20, 13:48
21 янв 20, 13:44    [22063676]     Ответить | Цитировать Сообщить модератору
 Re: нечеткий поиск  [new]
Swa111
Member

Откуда:
Сообщений: 123
Troglodit,

У себя реализовывали через алгоритм расчета расстояния по алгоритму дамерау левенштейн для каждой компоненты ФИО. при этом допускается расстояние не больше 1 (грубо говоря не более одной опечатки). + Дополнительный словарь наиболее частых опечаток. для ускорения поиска (особенно фамилий) принято что пользователи в первой букве ни когда не ошибаются. Так как алгоритм самописный и перекочевал из оракла не оптимизированным время поиска довольно большое (база ~140тыс ФИО) около 0,5-1 сек. С точки зрения оператора не так много.

Когда точности поиска стало не достаточно (стали приходить документы где есть только Фамилия И.О. + должность) добавили разбор должностей. Должность разбивалась на лексемы, из нее выкидывались части в которых чаще всего делали ошибки (указание категории или двойные должности), затем убирались малозначимые слова (определяются опытно), затем убираются все гласные. Так же находим расстояние по дамерау-левенштейну (не более 1). Естественно должности смотрим только по тем у кого подходят ФИО.
26 янв 20, 20:33    [22066812]     Ответить | Цитировать Сообщить модератору
 Re: нечеткий поиск  [new]
Troglodit
Member

Откуда:
Сообщений: 498
Swa111,
Спасибо за ответ.
Я пробовал использовать стандартную levenshtein, но результаты печальные, даже хуже чем все остальное.
В моем случае не фио и порядок слов может быть разным, да и ошибок более чем 2.
Но в моем случае те варианты, которые я пробовал давали плохой результат даже в когда все символы введены верно, но не
верен порядок.
Прмире.
Так же возможны стандартные ошибки в виде ввода похожих букв разных алфавитов.
Как то ограничить как с ФИО вряд ли получиться.
26 янв 20, 23:35    [22066872]     Ответить | Цитировать Сообщить модератору
 Re: нечеткий поиск  [new]
Ролг Хупин
Member

Откуда: Чебаркуль
Сообщений: 3411
"нечеткий поиск" - это что?

это типа гугловского "Did you mean?" - поиска с опечатками?
3 фев 20, 15:45    [22071852]     Ответить | Цитировать Сообщить модератору
 Re: нечеткий поиск  [new]
Troglodit
Member

Откуда:
Сообщений: 498
Ролг Хупин,
Да что то вроде этого.
3 фев 20, 22:59    [22072206]     Ответить | Цитировать Сообщить модератору
 Re: нечеткий поиск  [new]
Ы2
Member

Откуда:
Сообщений: 170
Troglodit, результат similarity() имеет смысл, если длины сравниваемых строк хотя бы по 20—25 символов и примерно равны между собой. Эта функция хороша, если вам нужно найти предложения, чем-то похожие на заданное, напр., с теми же словами в другом порядке, с заменой одного—двух слов из многих, с парафразом и т.п.
select
	similarity('В прошлый вторник Иванов купил будильник.', 'В прошлый вторник Иванов купил будильник.'),
	similarity('В прошлый вторник Иванов купил будильник.', 'Будильник Иванов купил в прошлый вторник .')
	similarity('В прошлый вторник Иванов купил будильник.', 'В прошлый вторник Иванову купили будильник.'),
	similarity('В прошлый вторник Иванов купил будильник.', 'В прошлый вторник Иванов купил штаны.'),
	similarity('В прошлый вторник Иванов купил будильник.', 'В прошлый вторник Иванова убили будильником.'),
	similarity('В прошлый вторник Иванов купил будильник.', 'В прошлый четверг Иванов купил будильник.')
;

levenshtein() же обычно хорош, когда у вас есть таблица всех словоформ, чтобы предлагать только то, что у вас точно есть.

Для нечеткого поиска вам, видимо, нужно построить «нечеткий индекс» — сделать что-то типа FTS по вашим метафонам.
4 фев 20, 01:00    [22072257]     Ответить | Цитировать Сообщить модератору
 Re: нечеткий поиск  [new]
Ролг Хупин
Member

Откуда: Чебаркуль
Сообщений: 3411
Troglodit
Ролг Хупин,
Да что то вроде этого.


Тогда надо немного с другого конца заходить, читаем Норвига
https://norvig.com/spell-correct.html

Я когда-то по его алгоритму сделал корректор для SQL Server
4 фев 20, 11:41    [22072506]     Ответить | Цитировать Сообщить модератору
Все форумы / PostgreSQL Ответить