Пользовательский анализатор Lucene для индексирования и запроса


Я работаю над lucene 4.7 и пытаюсь перенести один из анализаторов, которые мы используем в нашей конфигурации solr.

 <analyzer> 
  <charFilter class="solr.HTMLStripCharFilterFactory"/>
    <tokenizer class="solr.WhitespaceTokenizerFactory"/>
    <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>  
    <filter class="solr.WordDelimiterFilterFactory" 
            generateWordParts="1" 
            generateNumberParts="1" 
            catenateWords="1"
            catenateNumbers="1"
            catenateAll="0"
            splitOnCaseChange="0"
            splitOnNumerics="0"
            preserveOriginal="1"
    />
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.PorterStemFilterFactory"/>
  </analyzer>
Но я просто не могу понять, как использовать HTMLStripCharFilterFactory и WordDelimiterFilterFactory с конфигурацией, как указано выше. Кроме того, для моего запроса в solr мой анализатор выглядит следующим образом, как я могу добиться того же в lucene.
 <analyzer type="query">
    <tokenizer class="solr.WhitespaceTokenizerFactory"/>
    <filter class="solr.StopFilterFactory"
            ignoreCase="true"
            words="stopwords.txt"
            />
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.PorterStemFilterFactory"/>
  </analyzer>
1 2

1 ответ:

Документация пакета анализа объясняет, как использовать CharFilter. Вы оборачиваете читателя с ним в вашем переопределенном методе initReader.

Я предполагаю, что проблема с вашим WordDelimiterFilter заключается в том, что вы не знаете, как настроить параметры конфигурации, которые вы используете? Вы создаете int для передачи в конструктор, комбинируя соответствующие константы с двоичным и (&). например:

int config = WordDelimiterFilter.GENERATE_NUMBER_PARTS & WordDelimiterFilter.GENERATE_WORD_PARTS; //etc.

Итак, в конце концов вы можете получить что-то например:

//StopwordAnalyzerBase grants you some convenient ways to handle stop word sets.
public class MyAnalyzer extends StopwordAnalyzerBase {

    private final Version version = Version.LUCENE_47;
    private int wordDelimiterConfig;

    public MyAnalyzer() throws IOException {
        super(version, loadStopwordSet(new FileReader("stopwords.txt"), matchVersion));
        //Might as well load this config up front, along with the stop words
        wordDelimiterConfig = 
            WordDelimiterFilter.GENERATE_WORD_PARTS &
            WordDelimiterFilter.GENERATE_NUMBER_PARTS &
            WordDelimiterFilter.CATENATE_WORDS &
            WordDelimiterFilter.CATENATE_NUMBERS &
            WordDelimiterFilter.PRESERVE_ORIGINAL;
    }

    @Override
    protected TokenStreamComponents createComponents(String fieldName, Reader reader) {
        Tokenizer source = new WhitespaceTokenizer(version, reader);
        TokenStream filter = new WordDelimiterFilter(source, wordDelimiterConfig, null);
        filter = new LowercaseFilterFactory(version, filter);
        filter = new StopFilter(version, filter, stopwords);
        filter = new PorterStemFilter(filter);
        return new TokenStreamComponents(source, filter);
    }

    @Override
    protected Reader initReader(String fieldName, Reader reader) {
        return new HTMLStripCharFilter(reader);
    }
}
Примечание: я переместил StopFilter в after LowercaseFilter. Это делает его нечувствительным к регистру, если все определения стоп-слов записаны в нижнем регистре. Не знаю, если это проблематично из-за the WordDelimiterFilter. Если это так, то есть loadStopwordSet метод, который поддерживает нечувствительность к регистру, но я, честно говоря, не знаю, как его использовать.