Недавно на работе мне задали такую задачку: замутить в lucene поиск не только по точному совпадению ключевого слова, а также по его свловоформам.
А, надо сказать, проект у нас написан на .net и порт lucene там довольно старый (lucene 3.0.3). А что это значило для меня? А то, что штатной поддержки морфологии нужного мне языка не было. Я пошерстил интернет в поисках отвеа на вопрос: что же lucene может предложить в вопросах морфологии и стемминга той кучи языков, которую она не поодерживает из коробки?
В итоге выбор пал на связку lucene + hunspell, благо в версии lucene.net 3.0.3 hunspell входит в состав lucene contribs. Методика использования связки примерно такая:
А, надо сказать, проект у нас написан на .net и порт lucene там довольно старый (lucene 3.0.3). А что это значило для меня? А то, что штатной поддержки морфологии нужного мне языка не было. Я пошерстил интернет в поисках отвеа на вопрос: что же lucene может предложить в вопросах морфологии и стемминга той кучи языков, которую она не поодерживает из коробки?
В итоге выбор пал на связку lucene + hunspell, благо в версии lucene.net 3.0.3 hunspell входит в состав lucene contribs. Методика использования связки примерно такая:
- Нужно скачать словарь нужного языка для openoffice/libreoffice. Взять его можно здесь.
- Далее, из скачанного архива вытаскиваем два файла .aff и .dic и выкладываем их на сервер, в то место, где lucene сможет свободно изх прочитать.
- Я преобразовал файлы из iso-какойто-там кодировки в UTF-8. У нас в проекте все данные гоняются в UTF-8, ну и солвари тоже пускай в нем хранятся. Помимо перекодирования нужно отредактировать .aff файл и заменить указзаную в нем кодировку на UTF-8.
- Пишем простенький класс-анализатор:
public class LatvianHunspellAnalyzer: Analyzer
{
private static readonly HunspellDictionary Dictionary = GetDictionary(@"lv_LV");
private static HunspellDictionary GetDictionary(String culture)
{
using (var affixStream = OpenStream(culture + @".aff"))
using (var wordStream = OpenStream(culture + @".dic"))
{
if (affixStream != null && wordStream != null)
{
return new HunspellDictionary(affixStream, wordStream);
}
}
throw new InvalidOperationException("Missing affix- or word stream.");
}
protected static Stream OpenStream(String fileName)
{
return new FileStream(@"C:\inetpub\lucene\" + fileName, FileMode.Open);
}
public override TokenStream TokenStream(String fieldName, TextReader reader)
{
var stream = new StandardTokenizer(Version.LUCENE_29, reader);
TokenFilter filter = new LowerCaseFilter(stream);
filter = new HunspellStemFilter(filter, Dictionary);
return filter;
}
}
- Те части проекта, которые отвечают за сохранение данных в lucene индекс и чтение оттуда должны использовать этот анализатор (в моем случае LatvianHunspellAnalyzer, вы его можете назвать как угодно).
Вуаля, все ищется так как было задумано. Если чего-то не получится - спрашивайте.
Комментариев нет:
Отправить комментарий