Статьи

Написание плагина для анализа Solr

Поскольку мы работали над тем, чтобы добиться лучшего результата от фонетического поиска, который мы сейчас делаем в derduborЯ начал писать плагин для Solr, чтобы иметь возможность возвращать лучшие результаты поиска при поиске норвежских имен. До сих пор мы использовали стандартный фонетический фильтр из Solr 1.2, используя кодер с двойным метафоном для кодирования обычного токена в качестве фонетического значения. Проблема в том, что значение двойного метафона — это четыре простые буквы, что означает, что поисковые слова, такие как «trafikkontroll», будут иметь то же значение, что и «Dyrvik». Последнее — это имя, а первое — обычная поисковая строка, которая будет лучше отображаться в виде статьи. TRAFIKKONTROLL разрешается в TRFK в двойном метафоне, в то время как DYRVIK разрешается в DRVK. T и D считаются похожими, как и V и F, и вуаля, у вас есть совпадение в результатах поиска, но не визуальное (или семантическое, поскольку слова имеют совершенно разные значения).

Чтобы решить эту проблему, я решил написать собственный плагин фильтра, который мы могли бы настроить на имена, которые используются в Норвегии. Я расскажу о логике моих рассуждений в отношении формулировки позже и, надеюсь, опубликую полную функцию фильтра, которую мы применяем, но я оставлю это для другого поста.

Во-первых, вам нужна фабрика, которая может производить фильтры, когда Solr запрашивает их:

NorwegianNameFilterFactory.java:

    package no.derdubor.solr.analysis;
     
    import java.util.Map;
     
    import org.apache.solr.analysis.BaseTokenFilterFactory;
    import org.apache.lucene.analysis.TokenStream;
     
    public class NorwegianNameFilterFactory extends BaseTokenFilterFactory
    {
        Map<String,String> args;
     
        public Map<String,String> getArgs()
        {
            return args;
        }
     
        public void init(Map<String,String> args)
        {
            this.args = args;
        }
     
        public NorwegianNameFilter create(TokenStream input)
        {
            return new NorwegianNameFilter(input);
        }
    }

Чтобы скомпилировать этот пример самостоятельно, поместите файл в no / derdubor / solr / analysis / (что соответствует no.derdubor.solr.analysis; в операторе пакета) и запустите

javac -6 no/derdubor/solr/analysis/NorwegianNameFilterFactory.java

(для этого вам понадобятся apache-solr-core.jar и lucene-core.jar в вашем classpath)

скомпилировать это. Вам, конечно, также понадобится сам фильтр (который возвращается из метода create выше):

    package no.derdubor.solr.analysis;
     
    import java.io.IOException;
    import org.apache.lucene.analysis.Token;
    import org.apache.lucene.analysis.TokenFilter;
    import org.apache.lucene.analysis.TokenStream;
     
    public class NorwegianNameFilter extends TokenFilter
    {
        public NorwegianNameFilter(TokenStream input)
        {
            super(input);
        }
     
        public Token next() throws IOException
        {
            return parseToken(this.input.next());
        }
     
        public Token next(Token result) throws IOException
        {
            return parseToken(this.input.next());
        }
     
        protected Token parseToken(Token in)
        {
            /* do magic stuff with in.termBuffer() here (a char[] which can be manipulated) */
            /* set the changed length of the new term with in.setTermLength(); before returning it */
            return in;
        }
    }

Теперь вы должны быть в состоянии скомпилировать оба файла:

javac -6 no/derdubor/solr/analysis/*.java

После компиляции плагина создайте jar-файл, содержащий ваш плагин. Это будет «распространяемая» версия вашего плагина и должна содержать .class-файлы вашего приложения.

jar cvf derdubor-solr-norwegiannamefilter.jar no/derdubor/solr/analysis/*.class

Переместите только что созданный файл ( derdubor-solr-norwegiannamefilter.jar в приведенном выше примере) в домашнюю директорию Solr. Здесь вы храните каталог bin / и conf / (который содержит schema.xml и т. Д.). Создайте каталог lib в домашнем каталоге solr. Здесь будут жить ваши пользовательские библиотеки, поэтому скопируйте файл в этот каталог (lib /).

Перезапустите Solr и убедитесь, что все работает как надо. Если все выглядит нормально, пришло время включить ваш фильтр. В одной из ваших <filter> -цепей вы можете просто добавить элемент <filter>, чтобы вставить свой собственный фильтр в цепочку:

    <analyzer>
        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" catenateWords="1" />
        <filter class="solr.LowerCaseFilterFactory" />
        <filter class="no.derdubor.solr.analysis.NorwegianNameFilterFactory" />
    </analyzer>

Перезапустите Solr еще раз, и если все по-прежнему работает как надо, все готово! Время индексировать некоторые новые данные (помните, что вам нужно будет переиндексировать данные, чтобы все работало так, как вы ожидаете, поскольку при редактировании файлов конфигурации сохраненные данные не обрабатываются), и зафиксируйте их! Сделайте несколько поисков через интерфейс администратора, чтобы увидеть, что все работает как надо. Я использовал опцию «отладки» для… ну, отладки… моего плагина при его разработке. Очень полезный трюк — увидеть, к каким терминам относится ваш фильтр (если вы установите type = ”query”в разделе анализатора он будет применен ко всем запросам к этому полю), что будет показано в первом разделе отладки при просмотре результата (чтобы увидеть это, вам нужно прокрутить вниз до конца). Если вам нужно отладить что-то большее, вы можете подключить отладчик или просто использовать старый добрый проверенный способ печати ! (в конечном итоге это будет в catalina.out в журналах / в вашем каталоге tomcat). Удачи!

Потенциальные проблемы и как их решить

  • Если вы получаете сообщение об ошибке несовместимых версий классов, убедитесь, что на вашем поисковом сервере Solr вы используете ту же (или более новую) версию JVM (java -version), которую вы используете на своей собственной машине разработки (используйте -5 для принудительно использовать 1.5 совместимые файлы классов вместо 1.6 при компиляции).
  • Если вы получаете сообщение об ошибке, связанной с отсутствующей конфигурацией или чем-то похожим, или что Solr не может найти метод, который ищет (обычно запускаемый с помощью ReflectionException), не забудьте определить ваши классы общедоступными! открытый класс NorwegianNameFilter ваш друг! Прошло не менее получаса, пока я не понял, что это за простая проблема …

Любые комментарии и продолжение приветствуются!