Luceneアナライザーガイド

1概要

Lucene Analyzerは文書の索引付けと検索をしながらテキストを分析するために使用されます。

私達は私達のhttps://www.baeldung.com/lucene[introductory tutorial]でアナライザーについて簡単に述べました。

このチュートリアルでは、一般的に使用されるアナライザ、カスタムアナライザの作成方法、ドキュメントフィールドごとに異なるアナライザを割り当てる方法について説明します。

2 Mavenの依存関係

まず、これらの依存関係を pom.xml に追加する必要があります。

<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-core</artifactId>
    <version>7.4.0</version>
</dependency>
<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-queryparser</artifactId>
    <version>7.4.0</version>
</dependency>
<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-analyzers-common</artifactId>
    <version>7.4.0</version>
</dependency>

最新のLuceneバージョンはhttps://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.apache.lucene%22%20AND%20a%3A%22lucene-core%22[で見つけることができます。ここに]。

3 Luceneアナライザー

Lucene Analyzerはテキストをトークンに分割します。

  • アナライザは主にトークナイザとフィルタで構成されています** さまざまなアナライザはトークナイザとフィルタのさまざまな組み合わせで構成されています。

一般的に使用されているアナライザーの違いを説明するために、次の方法を使用します。

public List<String> analyze(String text, Analyzer analyzer) throws IOException{
    List<String> result = new ArrayList<String>();
    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一般的なLuceneアナライザ

それでは、一般的に使用されているLuceneアナライザーを見てみましょう。

4.1. 標準アナライザ

最も一般的に使用されるアナライザーである StandardAnalyzer から始めましょう。

private static final String SAMPLE__TEXT
  = "This is baeldung.com Lucene Analyzers test";

@Test
public void whenUseStandardAnalyzer__thenAnalyzed() throws IOException {
    List<String> result = analyze(SAMPLE__TEXT, new StandardAnalyzer());

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

StandardAnalyzer はURLとEメールを認識できます。

また、ストップワードを削除し、生成されたトークンを小文字にします。

4.2. ストップアナライザ

StopAnalyzer は、 LetterTokenizer、LowerCaseFilter 、および__StopFilterで構成されています。

@Test
public void whenUseStopAnalyzer__thenAnalyzed() throws IOException {
    List<String> result = analyze(SAMPLE__TEXT, new StopAnalyzer());

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

この例では、 __ LetterTokenizerはテキストを英字以外の文字で分割し、 StopFilter__はトークンリストからストップワードを削除します。

ただし、 StandardAnalyzer とは異なり、 StopAnalyzer はURLを認識できません。

4.3. シンプルアナライザー

SimpleAnalyzer は、 LetterTokenizer LowerCaseFilter で構成されています。

@Test
public void whenUseSimpleAnalyzer__thenAnalyzed() throws IOException {
    List<String> result = analyze(SAMPLE__TEXT, new SimpleAnalyzer());

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

ここで、 SimpleAnalyzer はストップワードを削除しませんでした。 URLも認識されません。

4.4. ホワイトアナライザ

WhitespaceAnalyzer は、テキストを空白文字で分割する WhitespaceTokenizer のみを使用します。

@Test
public void whenUseWhiteSpaceAnalyzer__thenAnalyzed() throws IOException {
    List<String> result = analyze(SAMPLE__TEXT, new WhitespaceAnalyzer());

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

4.5. KeywordAnalyzer

KeywordAnalyzer は、入力を単一のトークンにトークン化します。

@Test
public void whenUseKeywordAnalyzer__thenAnalyzed() throws IOException {
    List<String> result = analyze(SAMPLE__TEXT, new KeywordAnalyzer());

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

__KeywordAnalyzer __は、IDや郵便番号などのフィールドに役立ちます。

4.6. 言語アナライザ

EnglishAnalyzer FrenchAnalyzer 、および SpanishAnalyzer など、さまざまな言語用の特別なアナライザーもあります。

@Test
public void whenUseEnglishAnalyzer__thenAnalyzed() throws IOException {
    List<String> result = analyze(SAMPLE__TEXT, new EnglishAnalyzer());

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

ここでは、 StandardTokenizer StandardFilter EnglishPossessiveFilter LowerCaseFilter StopFilter 、および PorterStemFilter で構成される EnglishAnalyzer を使用しています。

5カスタムアナライザー

次に、カスタムアナライザーの作成方法を見てみましょう。同じカスタムアナライザーを2つの方法で作成します。

最初の例では、 CustomAnalyzer ビルダーを使用して、定義済みのトークナイザーとフィルターからアナライザーを構築します。

@Test
public void whenUseCustomAnalyzerBuilder__thenAnalyzed() throws IOException {
    Analyzer analyzer = CustomAnalyzer.builder()
      .withTokenizer("standard")
      .addTokenFilter("lowercase")
      .addTokenFilter("stop")
      .addTokenFilter("porterstem")
      .addTokenFilter("capitalization")
      .build();
    List<String> result = analyze(SAMPLE__TEXT, analyzer);

    assertThat(result, contains("Baeldung.com", "Lucen", "Analyz", "Test"));
}

私たちのアナライザーは EnglishAnalyzer と非常によく似ていますが、代わりにトークンを大文字にします。

2番目の例では、** Analyzer 抽象クラスを拡張し、 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);
    }
}

必要に応じて、カスタムトークナイザーまたはフィルターを作成してカスタムアナライザーに追加することもできます。

それでは、カスタムアナライザの動作を見てみましょう。この例ではhttps://www.baeldung.com/lucene[ InMemoryLuceneIndex ]を使用します。

@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<Document> documents = luceneIndex.searchIndex(query);
    assertEquals(1, documents.size());
}

6. PerFieldAnalyzerWrapper

最後に、 PerFieldAnalyzerWrapper を使用して、異なるアナライザを異なるフィールドに割り当てることができます。

まず、各アナライザーを特定のフィールドにマッピングするために analyzerMap を定義する必要があります。

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

「title」をカスタムアナライザに、「body」をEnglishAnalyzerにマッピングしました。

次に、 analyzerMap とデフォルトの Analyzer を指定して、 PerFieldAnalyzerWrapper を作成しましょう。

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

それでは、テストしましょう。

@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<Document> documents = luceneIndex.searchIndex(query);
    assertEquals(1, documents.size());

    query = new TermQuery(new Term("title", "Introduct"));
    documents = luceneIndex.searchIndex(query);
    assertEquals(1, documents.size());
}

7. 結論

私たちは、人気のあるLuceneアナライザ、カスタムアナライザの作成方法、およびフィールドごとに異なるアナライザを使用する方法について説明しました。

完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/lucene[found on GitHub]です。