Apache Lucene не фильтрует стоп-слова, несмотря на использование StopAnalyzer и StopFilter.

У меня есть модуль на основе Apache Lucene 5.5/6.0, который извлекает ключевые слова. Все работает нормально, кроме одного — Lucene не фильтрует стоп-слова.

Я попытался включить фильтрацию стоп-слов двумя разными способами.

Подход №1:

tokenStream = new StopFilter(new ASCIIFoldingFilter(new ClassicFilter(new LowerCaseFilter(stdToken))), EnglishAnalyzer.getDefaultStopSet());
tokenStream.reset();

Подход 2.

tokenStream = new StopFilter(new ClassicFilter(new LowerCaseFilter(stdToken)), StopAnalyzer.ENGLISH_STOP_WORDS_SET);
tokenStream.reset();

Полный код доступен здесь:
https://stackoverflow.com/a/36237769/462347.

Мои вопросы:

  1. Почему Lucene не фильтрует стоп-слова?
  2. Как включить фильтрацию стоп-слов в Lucene 5.5/6.0?

person Mike B.    schedule 26.03.2016    source источник


Ответы (2)


Только что протестировали как подход 1, так и подход 2, и оба они, похоже, отлично отфильтровывают стоп-слова. Вот как я это тестировал:

public static void main(String[] args) throws IOException, ParseException, org.apache.lucene.queryparser.surround.parser.ParseException 
{
     StandardTokenizer stdToken = new StandardTokenizer();
     stdToken.setReader(new StringReader("Some stuff that is in need of analysis"));
     TokenStream tokenStream;

     //You're code starts here
     tokenStream = new StopFilter(new ASCIIFoldingFilter(new ClassicFilter(new LowerCaseFilter(stdToken))), EnglishAnalyzer.getDefaultStopSet());
     tokenStream.reset();
     //And ends here

     CharTermAttribute token = tokenStream.getAttribute(CharTermAttribute.class);
     while (tokenStream.incrementToken()) {
         System.out.println(token.toString());
     }
     tokenStream.close();
}

Результаты:

некоторые
вещи
нуждаются
в анализе

Что устранило четыре стоп-слова в моем образце.

person femtoRgon    schedule 27.03.2016
comment
Проблема в том, что Lucene не отфильтровывает такие слова, как we, I и другие распространенные английские слова. Должен ли я прикрепить другой расширенный словарь стоп-слов? Предоставляет ли Lucene другие словари стоп-слов? - person Mike B.; 27.03.2016
comment
EnglishAnalyzer и StandardAnalyzer используют один и тот же набор стоп-слов, поэтому я не верю, что в lucene есть более обширный стоп-лист. Так что, да, вам, вероятно, придется создать свой собственный. Если вы используете StandardAnalyzer, это упрощает сохранение стоп-слов в текстовом файле и передачу средства чтения в конструктор. - person femtoRgon; 27.03.2016
comment
Вы имеете в виду StandardAnalyzer или StandardTokenizer? Я использую StandardAnalyzer.STOP_WORDS_SET, но конструктор для StandardAnalyzer не используется. Напротив, у меня есть stdToken.setReader(new StringReader(fullText));. Где именно я должен разместить свой список стоп-слов? - person Mike B.; 27.03.2016
comment
Вам нужно передать CharArraySet стоп-слов в StopFilter. StandardAnalyzer просто есть удобный ctor, что делает его удобным. Чтобы построить из файла, вы должны использовать WordListLoader.getWordSet. Или вы можете просто создать CharArraySet работать с вами довольно просто. - person femtoRgon; 27.03.2016
comment
Отлично, отдельное спасибо за WordlistLoader.getWordSet. - person Mike B.; 27.03.2016

Я ожидал, что ловушка была в списке стоп-слов Lucene по умолчанию, он намного шире.

Вот код, который по умолчанию пытается загрузить настраиваемый список стоп-слов, а в случае неудачи использует стандартный:

CharArraySet stopWordsSet;

try {
    // use customized stop words list
    String stopWordsDictionary = FileUtils.readFileToString(new File(%PATH_TO_FILE%));
    stopWordsSet = WordlistLoader.getWordSet(new StringReader(stopWordsDictionary));
} catch (FileNotFoundException e) {
    // use standard stop words list
    stopWordsSet = CharArraySet.copy(StandardAnalyzer.STOP_WORDS_SET);
}

tokenStream = new StopFilter(new ASCIIFoldingFilter(new ClassicFilter(new LowerCaseFilter(stdToken))), stopWordsSet);
tokenStream.reset();
person Mike B.    schedule 27.03.2016