1. 概要

Apache Luceneは全文検索エンジンであり、さまざまなプログラミング言語で使用できます。 Luceneの使用を開始するには、ここにある紹介記事を参照してください。

この簡単な記事では、テキストファイルにインデックスを付け、そのファイル内のサンプルStringsとテキストスニペットを検索します。

2. Mavenのセットアップ

最初に必要な依存関係を追加しましょう:

<dependency>        
    <groupId>org.apache.lucene</groupId>          
    <artifactId>lucene-core</artifactId>
    <version>7.1.0</version>
</dependency>

最新バージョンはここにあります。

また、検索クエリを解析するには、次のものが必要です。

<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-queryparser</artifactId>
    <version>7.1.0</version>
</dependency>

最新バージョンここを確認することを忘れないでください。

3. ファイルシステムディレクトリ

ファイルにインデックスを付けるには、最初にファイルシステムインデックスを作成する必要があります。

Luceneは、ファイルシステムインデックスを作成するためのFSDirectoryクラスを提供します。

Directory directory = FSDirectory.open(Paths.get(indexPath));

ここで、indexPathはディレクトリの場所です。 ディレクトリが存在しない場合、Luceneがディレクトリを作成します。

Luceneは、抽象の3つの具体的な実装を提供します FSDirectory クラス: SimpleFSDirectory、NIOFSDirectory、およびMMapDirectory。 それらのそれぞれは、特定の環境で特別な問題を抱えている可能性があります。

たとえば、 SimpleFSDirectoryは、複数のスレッドが同じファイルから読み取るときにブロックするため、同時パフォーマンスが低下します。

同様に、 NIOFSDirectoryとMMapDirectoryの実装は、それぞれWindowsのファイルチャネルの問題とメモリリリースの問題に直面しています。

このような環境の特殊性を克服するために、LuceneはFSDirectory.open()メソッドを提供します。呼び出されると、環境に応じて最適な実装を選択しようとします。

4. インデックステキストファイル

インデックスディレクトリを作成したら、先に進んでファイルをインデックスに追加しましょう。

public void addFileToIndex(String filepath) {

    Path path = Paths.get(filepath);
    File file = path.toFile();
    IndexWriterConfig indexWriterConfig
     = new IndexWriterConfig(analyzer);
    Directory indexDirectory = FSDirectory
      .open(Paths.get(indexPath));
    IndexWriter indexWriter = new IndexWriter(
      indexDirectory, indexWriterConfig);
    Document document = new Document();

    FileReader fileReader = new FileReader(file);
    document.add(
      new TextField("contents", fileReader));
    document.add(
      new StringField("path", file.getPath(), Field.Store.YES));
    document.add(
      new StringField("filename", file.getName(), Field.Store.YES));

    indexWriter.addDocument(document);
    indexWriter.close();
}

ここでは、「path」と「filename」という名前の2つの StringFields と、「contents」という名前のTextFieldを使用してドキュメントを作成します。

fileReaderインスタンスを2番目のパラメータとしてTextFieldに渡すことに注意してください。 IndexWriter。を使用してドキュメントがインデックスに追加されます

TextFieldまたはStringFieldコンストラクターの3番目の引数は、フィールドの値も格納されるかどうかを示します。

最後に、 IndexWriterclose()を呼び出して、インデックスファイルからロックを適切に閉じて解放します。

5. インデックスファイルの検索

次に、インデックスを作成したファイルを検索しましょう。

public List<Document> searchFiles(String inField, String queryString) {
    Query query = new QueryParser(inField, analyzer)
      .parse(queryString);
    Directory indexDirectory = FSDirectory
      .open(Paths.get(indexPath));
    IndexReader indexReader = DirectoryReader
      .open(indexDirectory);
    IndexSearcher searcher = new IndexSearcher(indexReader);
    TopDocs topDocs = searcher.search(query, 10);
    
    return topDocs.scoreDocs.stream()
      .map(scoreDoc -> searcher.doc(scoreDoc.doc))
      .collect(Collectors.toList());
}

機能をテストしてみましょう。

@Test
public void givenSearchQueryWhenFetchedFileNamehenCorrect(){
    String indexPath = "/tmp/index";
    String dataPath = "/tmp/data/file1.txt";
    
    Directory directory = FSDirectory
      .open(Paths.get(indexPath));
    LuceneFileSearch luceneFileSearch 
      = new LuceneFileSearch(directory, new StandardAnalyzer());
    
    luceneFileSearch.addFileToIndex(dataPath);
    
    List<Document> docs = luceneFileSearch
      .searchFiles("contents", "consectetur");
    
    assertEquals("file1.txt", docs.get(0).get("filename"));
}

indexPath の場所にファイルシステムインデックスを作成し、file1.txt。にインデックスを付ける方法に注目してください。

次に、「contents」フィールドでStringconsectetur」を検索します。

6. 結論

この記事は、ApacheLuceneを使用したテキストのインデックス作成と検索の簡単なデモンストレーションでした。 Luceneのインデックス作成、シアリング、クエリの詳細については、Luceneの紹介記事を参照してください。

いつものように、例のコードはGithubにあります。