Une recherche de fichier simple avec Lucene

Une recherche de fichier simple avec Lucene

1. Vue d'ensemble

Apache Lucene est un moteur de recherche en texte intégral qui peut être utilisé par différents langages de programmation. Pour commencer avec Lucene, veuillez vous référer à notre introductionarticle here.

Dans cet article rapide, nous allons indexer un fichier texte et rechercher des échantillonsStrings et des extraits de texte dans ce fichier.

2. Maven Setup

Ajoutons d'abord les dépendances nécessaires:


    org.apache.lucene
    lucene-core
    7.1.0

La dernière version peut être trouvéehere.

De plus, pour analyser nos requêtes de recherche, nous aurons besoin des éléments suivants:


    org.apache.lucene
    lucene-queryparser
    7.1.0

N'oubliez pas de vérifier la dernière versionhere.

3. Répertoire du système de fichiers

Pour indexer des fichiers, nous devons d'abord créer un index du système de fichiers.

Lucene fournit la classeFSDirectory pour créer un index de système de fichiers:

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

IciindexPath est l'emplacement du répertoire. If the directory doesn’t exist, Lucene will create it.

Lucene fournit trois implémentations concrètes de la classe abstraiteFSDirectory:SimpleFSDirectory, NIOFSDirectory, and MMapDirectory. Chacune d'elles peut avoir des problèmes particuliers avec un environnement donné.

Par exemple,SimpleFSDirectory has poor concurrent performance as it blocks when multiple threads read from the same file.

De même, lesNIOFSDirectory and MMapDirectory implementations face file-channel issues in Windows and memory release problems respectively.

To overcome such environment peculiarities Lucene provides the FSDirectory.open() method. Lorsqu'il est appelé, il essaie de choisir la meilleure implémentation en fonction de l'environnement.

4. Fichier texte d'index

Une fois que nous avons créé le répertoire d'index, allons-y et ajoutons un fichier à l'index:

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

Ici, nous créons un document avec deuxStringFields nommés «chemin» et «nom de fichier» et unTextFieldappelé «contenu».

Notez que nous transmettons l'instancefileReader comme deuxième paramètre auxTextField. Le document est ajouté à l'index à l'aide desIndexWriter.

Le troisième argument du constructeurTextField ouStringField indique si la valeur du champ sera également stockée.

Enfin, nous invoquons lesclose() desIndexWriter pour fermer et libérer le verrou des fichiers d'index.

5. Rechercher des fichiers indexés

Examinons maintenant les fichiers que nous avons indexés:

public List 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());
}

Voyons maintenant la fonctionnalité:

@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 docs = luceneFileSearch
      .searchFiles("contents", "consectetur");

    assertEquals("file1.txt", docs.get(0).get("filename"));
}

Remarquez comment nous créons un index de système de fichiers à l'emplacementindexPath et indexons lesfile1.txt.

Ensuite, nous cherchons simplement leString «consectetur» dans le champ“contents”.

6. Conclusion

Cet article était une démonstration rapide de l'indexation et de la recherche de texte avec Apache Lucene. Pour en savoir plus sur l'indexation, la saisie et les requêtes de Lucene, veuillez consulter nosintroduction to Lucene article.

Comme toujours, le code des exemples peut être trouvéover on Github.