Мне неизвестно о каком-либо решении, в котором вы бы указали точное количество допустимых изменений.
У этого подхода, во всяком случае, есть серьезные недостатки: что означает совпадение слова "foo" с числом до 3 изменения? Просто сопоставить что-нибудь? Как видите, решение, которое работает с различными длинами сроков, может быть лучше.
Одним из решений является индексирование n-грамм. Я говорю не о ребро-нграммах, как вы уже делаете, а о реальных нграммах, извлеченных из всего термина, а не только из ребер. Таким образом, при индексации 2 граммов foooo
вы должны индексировать:
fo
oo
(встречается несколько раз)
И при запросе термин fouuu
будет преобразован в:
... и он будет соответствовать индексируемому документу, поскольку у них есть хотя бы один общий термин (fo
).
Очевидно, что есть некоторые недостатки. С 2 граммами термин fuuuu
не будет соответствовать foooo
, но термин barfooo
будет соответствовать, потому что они имеют общий 2 грамма. Таким образом, вы получите ложные срабатывания. Чем дольше граммы, тем меньше вероятность получения ложных срабатываний, но тем менее нечетким будет ваш поиск.
Эти ложные срабатывания можно убрать go, полагаясь на оценку и сортировку по баллам. разместить лучшие совпадения первыми в списке результатов. Например, вы можете настроить фильтр ngram для сохранения исходного термина, чтобы fooo
преобразовывалось в [fooo
, fo
, oo
] вместо просто [fo
, oo
], и, таким образом, точный поиск fooo
будет иметь лучший результат для документа, содержащего fooo
, чем для документа, содержащего barfooo
(так как совпадений больше). Вы также можете настроить несколько отдельных полей: одно без ngram, одно с 3-граммами, одно с 2-граммами и создать логический запрос с предложением should
для каждого поля: чем больше совпадений, тем выше будет оценка да, и чем выше вы найдете документ в хитах.
Кроме того, я бы сказал, что fooo
и аналогичные являются действительно искусственными примерами, и вы вряд ли будете иметь эти термины в реальном мире. набор данных; Вы должны попробовать любое решение с реальным набором данных и посмотреть, работает ли оно достаточно хорошо. Если вам нужен нечеткий поиск, вам придется принять некоторые ложных срабатываний: вопрос не в том, существуют ли они, а в том, достаточно ли они редки, чтобы пользователи все еще могли легко найти то, что искали.
Чтобы использовать нграммы, примените фильтр n-грамм, используя org.apache.lucene.analysis.ngram.NGramFilterFactory
. Применяйте его как при индексировании, так и при запросах. Используйте параметры minGramSize
/ maxGramSize
, чтобы настроить размер нграмм, и keepShortTerm
(true
/ false
), чтобы указать, сохранять ли исходный термин или нет.
Вы можете сохранить фильтр грани-нграмм или нет; посмотреть, если это улучшает актуальность ваших результатов? Я подозреваю, что это может немного улучшить релевантность, если вы используете keepShortTerm = true
. В любом случае, обязательно примените фильтр ребра-ngram перед фильтром ngram.