Ръководство за анализатори на луцен

1. Общ преглед

Lucene Analyzers се използват за анализ на текст при индексиране и търсене на документи.

Накратко споменахме анализаторите в нашия уводен урок.

В този урок ще обсъдим често използваните анализатори, как да изградим нашия потребителски анализатор и как да присвоим различни анализатори за различни полета на документа .

2. Зависимости на Maven

Първо, трябва да добавим тези зависимости към нашия pom.xml :

 org.apache.lucene lucene-core 7.4.0   org.apache.lucene lucene-queryparser 7.4.0   org.apache.lucene lucene-analyzers-common 7.4.0 

Най-новата версия на Lucene можете да намерите тук.

3. Анализатор на луцен

Lucene Analyzers разделят текста на символи.

Анализаторите се състоят главно от маркери и филтри. Различните анализатори се състоят от различни комбинации от маркери и филтри.

За да демонстрираме разликата между често използваните анализатори, ще използваме следния метод:

public List analyze(String text, Analyzer analyzer) throws IOException{ List result = new ArrayList(); TokenStream tokenStream = analyzer.tokenStream(FIELD_NAME, text); CharTermAttribute attr = tokenStream.addAttribute(CharTermAttribute.class); tokenStream.reset(); while(tokenStream.incrementToken()) { result.add(attr.toString()); } return result; }

Този метод преобразува даден текст в списък с маркери, използвайки дадения анализатор.

4. Обикновени анализатори на луцен

Сега нека да разгледаме някои често използвани анализатори на луцен.

4.1. StandardAnalyzer

Ще започнем с StandardAnalyzer, който е най-често използваният анализатор:

private static final String SAMPLE_TEXT = "This is baeldung.com Lucene Analyzers test"; @Test public void whenUseStandardAnalyzer_thenAnalyzed() throws IOException { List result = analyze(SAMPLE_TEXT, new StandardAnalyzer()); assertThat(result, contains("baeldung.com", "lucene", "analyzers","test")); }

Имайте предвид, че StandardAnalyzer може да разпознава URL адреси и имейли.

Също така премахва думите за спиране и малки букви генерираните жетони.

4.2. StopAnalyzer

В StopAnalyzer състои от LetterTokenizer, LowerCaseFilter и StopFilter:

@Test public void whenUseStopAnalyzer_thenAnalyzed() throws IOException { List result = analyze(SAMPLE_TEXT, new StopAnalyzer()); assertThat(result, contains("baeldung", "com", "lucene", "analyzers", "test")); }

В този пример LetterTokenizer разделя текста на небуквени знаци, докато StopFilter премахва стоп думи от списъка с маркери .

Въпреки това, за разлика от StandardAnalyzer , StopAnalyzer не може да разпознава URL адреси.

4.3. SimpleAnalyzer

SimpleAnalyzer се състои от LetterTokenizer и LowerCaseFilter :

@Test public void whenUseSimpleAnalyzer_thenAnalyzed() throws IOException { List result = analyze(SAMPLE_TEXT, new SimpleAnalyzer()); assertThat(result, contains("this", "is", "baeldung", "com", "lucene", "analyzers", "test")); }

Тук SimpleAnalyzer не премахна думите за спиране. Освен това не разпознава URL адреси.

4.4. WhitespaceAnalyzer

На WhitespaceAnalyzer употреби само WhitespaceTokenizer който разделя текст от интервали символи:

@Test public void whenUseWhiteSpaceAnalyzer_thenAnalyzed() throws IOException { List result = analyze(SAMPLE_TEXT, new WhitespaceAnalyzer()); assertThat(result, contains("This", "is", "baeldung.com", "Lucene", "Analyzers", "test")); }

4.5. KeywordAnalyzer

В KeywordAnalyzer tokenizes вход в един жетон:

@Test public void whenUseKeywordAnalyzer_thenAnalyzed() throws IOException { List result = analyze(SAMPLE_TEXT, new KeywordAnalyzer()); assertThat(result, contains("This is baeldung.com Lucene Analyzers test")); }

В KeywordAnalyzer е полезно за области като идентификатори и zipcodes.

4.6. Езикови анализатори

Има и специални анализатори за различни езици като EnglishAnalyzer , FrenchAnalyzer и SpanishAnalyzer :

@Test public void whenUseEnglishAnalyzer_thenAnalyzed() throws IOException { List result = analyze(SAMPLE_TEXT, new EnglishAnalyzer()); assertThat(result, contains("baeldung.com", "lucen", "analyz", "test")); }

Ето, ние сме с помощта на EnglishAnalyzer който се състои от StandardTokenizer , StandardFilter , EnglishPossessiveFilter , LowerCaseFilter , StopFilter и PorterStemFilter .

5. Персонализиран анализатор

След това нека видим как да изградим нашия потребителски анализатор. Ще изградим един и същ персонализиран анализатор по два различни начина.

В първия пример ще използваме конструктора CustomAnalyzer , за да изградим нашия анализатор от предварително дефинирани токенизатори и филтри :

@Test public void whenUseCustomAnalyzerBuilder_thenAnalyzed() throws IOException { Analyzer analyzer = CustomAnalyzer.builder() .withTokenizer("standard") .addTokenFilter("lowercase") .addTokenFilter("stop") .addTokenFilter("porterstem") .addTokenFilter("capitalization") .build(); List result = analyze(SAMPLE_TEXT, analyzer); assertThat(result, contains("Baeldung.com", "Lucen", "Analyz", "Test")); }

Нашият анализатор е много подобен на EnglishAnalyzer , но вместо това той изписва с главни букви символите.

Във втория пример ще изградим същия анализатор, като разширим абстрактния клас на анализатора и заменим метода createComponents () :

public class MyCustomAnalyzer extends Analyzer { @Override protected TokenStreamComponents createComponents(String fieldName) { StandardTokenizer src = new StandardTokenizer(); TokenStream result = new StandardFilter(src); result = new LowerCaseFilter(result); result = new StopFilter(result, StandardAnalyzer.STOP_WORDS_SET); result = new PorterStemFilter(result); result = new CapitalizationFilter(result); return new TokenStreamComponents(src, result); } }

Също така можем да създадем наш персонализиран токенизатор или филтър и да го добавим към нашия потребителски анализатор, ако е необходимо.

Now, let's see our custom analyzer in action – we'll use InMemoryLuceneIndex in this example:

@Test public void givenTermQuery_whenUseCustomAnalyzer_thenCorrect() { InMemoryLuceneIndex luceneIndex = new InMemoryLuceneIndex( new RAMDirectory(), new MyCustomAnalyzer()); luceneIndex.indexDocument("introduction", "introduction to lucene"); luceneIndex.indexDocument("analyzers", "guide to lucene analyzers"); Query query = new TermQuery(new Term("body", "Introduct")); List documents = luceneIndex.searchIndex(query); assertEquals(1, documents.size()); }

6. PerFieldAnalyzerWrapper

Finally, we can assign different analyzers to different fields using PerFieldAnalyzerWrapper.

First, we need to define our analyzerMap to map each analyzer to a specific field:

Map analyzerMap = new HashMap(); analyzerMap.put("title", new MyCustomAnalyzer()); analyzerMap.put("body", new EnglishAnalyzer());

We mapped the “title” to our custom analyzer and the “body” to the EnglishAnalyzer.

Next, let's create our PerFieldAnalyzerWrapper by providing the analyzerMap and a default Analyzer:

PerFieldAnalyzerWrapper wrapper = new PerFieldAnalyzerWrapper( new StandardAnalyzer(), analyzerMap);

Now, let's test it:

@Test public void givenTermQuery_whenUsePerFieldAnalyzerWrapper_thenCorrect() { InMemoryLuceneIndex luceneIndex = new InMemoryLuceneIndex(new RAMDirectory(), wrapper); luceneIndex.indexDocument("introduction", "introduction to lucene"); luceneIndex.indexDocument("analyzers", "guide to lucene analyzers"); Query query = new TermQuery(new Term("body", "introduct")); List documents = luceneIndex.searchIndex(query); assertEquals(1, documents.size()); query = new TermQuery(new Term("title", "Introduct")); documents = luceneIndex.searchIndex(query); assertEquals(1, documents.size()); }

7. Conclusion

We discussed popular Lucene Analyzers, how to build a custom analyzer and how to use a different analyzer per field.

Пълният изходен код може да бъде намерен на GitHub.