Нечеткий поиск, который работает хорошо

852 views
Skip to first unread message

Igor Z.

unread,
May 30, 2014, 1:13:30 AM5/30/14
to elastics...@googlegroups.com
Доброго времени,
задача простая: искать с неким процентом совпадения, с расчетом на возможные опечатки. Текущая реализация такая:

_client.Search<SearchObject>(body =>
body.Query(q => q.Fuzzy(fz => fz
               .OnField(f => f.PropertyValue)
               .Value(key.ToLowerInvariant())
               .PrefixLength(0)
               .MinSimilarity(similarity)))).Size(maxResultCount)); 

Почему так? Пробовал fuzzy_like_this, он почему-то долго очень работает. Вопрос вот в чем: как считается подобие для строк разной длины? Ну например:

"водный" и "вадный" - расстояние по Левенштейну 1, если мы ищем с min_similarity = 0.5, если я правильно понимаю, работает такая формула:  length("водный") * 0.5 = 3, т.е. расстояние до 3 будет находить. 
НО! если в индексе лежит строка "Государственная академия водного транспорта" - расстояние будет намного больше, и поиск ее не находит! Хотя степень подобия фрагмента этой строки в общем-то такая же. Это дико не практично: если уменьшать similarity, то на коротких строках будет находить все подряд, строки в поисковых объектах очень разной длины, как отвязать от этой длины поиск, и заставить его одинаково хорошо искать по подстроке в строке любой длины, с некоторым люфтом подобия?

Заранее спасибо за помощь!

Igor Motov

unread,
Jun 1, 2014, 11:23:30 AM6/1/14
to elastics...@googlegroups.com
Я что-то не соображу, это какой клиент. Так что не знаю, поддерживает это ваш клиент или нет, но запрос fuzzy кроме min_similarity поддерживет еще и параметер fuzziness. См - http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-fuzzy-query.html#_string_fields_2

Igor Z.

unread,
Jun 2, 2014, 12:28:56 AM6/2/14
to elastics...@googlegroups.com
Это Nest, версии 0.12, и вроде как fuzziness - это то же самое, что min_similarity, по крайней мере я в GitHub'е Nest'а видел тикет на переименование второго в первое. Мой вопрос, в принципе, не привязан к клиенту, он в целом по fuzzyQuery. В той ссылке, что Вы привели, fuzziness - это целое число, расстояние по Левенштейну, в Nest это double - насколько я понял, этот коэффициент умножается на длину фразы (поисковой или терма, если у них разная длина - вот этого я не смог найти), получается целочисленное расстояние. Но опять же, не в этом вопрос. Не могу понять, как сделать нечеткий поиск в ElasticSearch,  не зависящий от длины строки, где идет поиск.

Igor Motov

unread,
Jun 2, 2014, 7:01:05 AM6/2/14
to elastics...@googlegroups.com
Попробуйте поставить fuzziness в 1 или 2 - в последних версиях elasticsearch min_similarity парсится так же как и fuzziness. Если значение 1 или 2, то оно работает как fuzziness если между 0 и 1 - то как min_similarity. Кстати, какую версию elasticsearch вы используете?
Reply all
Reply to author
Forward
0 new messages