Leitfaden für Lucene-Analysatoren

Leitfaden für Lucene-Analysatoren

1. Überblick

Lucene Analyzer werden zum Analysieren von Text beim Indizieren und Durchsuchen von Dokumenten verwendet.

Wir haben die Analysatoren in unserenintroductory tutorial kurz erwähnt.

In diesem Tutorial werdenwe’ll discuss commonly used Analyzers, how to construct our custom analyzer and how to assign different analyzers for different document fields.

2. Maven-Abhängigkeiten

Zuerst müssen wir diese Abhängigkeiten zu unserenpom.xml hinzufügen:


    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

Die neueste Lucene-Version finden Sie unterhere.

3. Lucene Analyzer

Lucene Analyzer teilen den Text in Token auf.

Analyzers mainly consist of tokenizers and filters. Verschiedene Analysatoren bestehen aus verschiedenen Kombinationen von Tokenisierern und Filtern.

Um den Unterschied zwischen häufig verwendeten Analysegeräten zu demonstrieren, verwenden wir die folgende Methode:

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;
}

Diese Methode konvertiert einen gegebenen Text unter Verwendung des gegebenen Analysators in eine Liste von Token.

4. Gängige Lucene-Analysatoren

Schauen wir uns nun einige häufig verwendete Lucene-Analysegeräte an.

4.1. StandardAnalyzer

Wir beginnen mitStandardAnalyzer, dem am häufigsten verwendeten Analysator:

private static final String SAMPLE_TEXT
  = "This is example.com Lucene Analyzers test";

@Test
public void whenUseStandardAnalyzer_thenAnalyzed() throws IOException {
    List result = analyze(SAMPLE_TEXT, new StandardAnalyzer());

    assertThat(result,
      contains("example.com", "lucene", "analyzers","test"));
}

Beachten Sie, dassStandardAnalyzer URLs und E-Mails erkennen können.

Außerdem werden Stoppwörter entfernt und die generierten Token werden kleiner dargestellt.

4.2. StopAnalyzer

DieStopAnalyzer bestehen ausLetterTokenizer, LowerCaseFilter undStopFilter:

@Test
public void whenUseStopAnalyzer_thenAnalyzed() throws IOException {
    List result = analyze(SAMPLE_TEXT, new StopAnalyzer());

    assertThat(result,
      contains("example", "com", "lucene", "analyzers", "test"));
}

In diesem Beispiel teiltLetterTokenizer Text durch Nicht-Buchstaben-Zeichen, währendStopFilter Stoppwörter aus der Token-Liste entfernt.

Im Gegensatz zuStandardAnalyzer kannStopAnalyzer URLs jedoch nicht erkennen.

4.3. SimpleAnalyzer

SimpleAnalyzer besteht ausLetterTokenizer undLowerCaseFilter:

@Test
public void whenUseSimpleAnalyzer_thenAnalyzed() throws IOException {
    List result = analyze(SAMPLE_TEXT, new SimpleAnalyzer());

    assertThat(result,
      contains("this", "is", "example", "com", "lucene", "analyzers", "test"));
}

Hier haben dieSimpleAnalyzer keine Stoppwörter entfernt. URLs werden ebenfalls nicht erkannt.

4.4. WhitespaceAnalyzer

DasWhitespaceAnalyzer verwendet nur einWhitespaceTokenizer, das Text durch Leerzeichen aufteilt:

@Test
public void whenUseWhiteSpaceAnalyzer_thenAnalyzed() throws IOException {
    List result = analyze(SAMPLE_TEXT, new WhitespaceAnalyzer());

    assertThat(result,
      contains("This", "is", "example.com", "Lucene", "Analyzers", "test"));
}

4.5. KeywordAnalyzer

DasKeywordAnalyzer Token gibt die Eingabe in ein einzelnes Token ein:

@Test
public void whenUseKeywordAnalyzer_thenAnalyzed() throws IOException {
    List result = analyze(SAMPLE_TEXT, new KeywordAnalyzer());

    assertThat(result, contains("This is example.com Lucene Analyzers test"));
}

DasKeywordAnalyzer ist nützlich für Felder wie IDs und Postleitzahlen.

4.6. Sprachanalysatoren

Es gibt auch spezielle Analysegeräte für verschiedene Sprachen wieEnglishAnalyzer,FrenchAnalyzer undSpanishAnalyzer:

@Test
public void whenUseEnglishAnalyzer_thenAnalyzed() throws IOException {
    List result = analyze(SAMPLE_TEXT, new EnglishAnalyzer());

    assertThat(result, contains("example.com", "lucen", "analyz", "test"));
}

Hier verwenden wirEnglishAnalyzer, das ausStandardTokenizer,StandardFilter,EnglishPossessiveFilter,LowerCaseFilter,StopFilter undPorterStemFilterbesteht. s.

5. Benutzerdefinierter Analysator

Als nächstes sehen wir uns an, wie Sie unseren benutzerdefinierten Analysator erstellen. Wir werden denselben benutzerdefinierten Analysator auf zwei verschiedene Arten erstellen.

Im ersten Beispiel istwe’ll use the CustomAnalyzer builder to construct our analyzer from predefined tokenizers and filters:

@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("example.com", "Lucen", "Analyz", "Test"));
}

Unser Analysator istEnglishAnalyzer sehr ähnlich, aktiviert jedoch stattdessen die Token.

Im zweiten Beispielwe’ll build the same analyzer by extending the Analyzer abstract class and overriding the createComponents() method:

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);
    }
}

Wir können auch unseren benutzerdefinierten Tokenizer oder Filter erstellen und ihn bei Bedarf unserem benutzerdefinierten Analysator hinzufügen.

Lassen Sie uns nun unseren benutzerdefinierten Analysator in Aktion sehen. In diesem Beispiel verwenden wirInMemoryLuceneIndex:

@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

Schließlichwe can assign different analyzers to different fields using PerFieldAnalyzerWrapper.

Zuerst müssen wir unsereanalyzerMapdefinieren, um jeden Analysator einem bestimmten Feld zuzuordnen:

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

Wir haben den „Titel“ unserem benutzerdefinierten Analysator und den „Körper“ dem EnglishAnalyzer zugeordnet.

Als Nächstes erstellen wir unserePerFieldAnalyzerWrapper, indem wir dieanalyzerMap und eine StandardAnalyzer angeben:

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

Testen wir es jetzt:

@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. Fazit

Wir haben beliebte Lucene-Analysatoren besprochen, wie man einen benutzerdefinierten Analysator erstellt und wie man einen anderen Analysator pro Feld verwendet.

Der vollständige Quellcode kannfound on GitHub sein.