Een eenvoudig bestand zoeken met Lucene

1. Overzicht

Apache Lucene is een full-text zoekmachine die door verschillende programmeertalen kan worden gebruikt. Raadpleeg hier ons inleidende artikel om aan de slag te gaan met Lucene.

In dit korte artikel indexeren we een tekstbestand en een zoekvoorbeeld Snaren en tekstfragmenten in dat bestand.

2. Maven-instellingen

Laten we eerst de nodige afhankelijkheden toevoegen:

 org.apache.lucene lucene-core 7.1.0 

De laatste versie vind je hier.

Voor het ontleden van onze zoekopdrachten hebben we ook het volgende nodig:

 org.apache.lucene lucene-queryparser 7.1.0 

Vergeet niet om hier de laatste versie te controleren.

3. Bestandssysteemmap

Om bestanden te indexeren, moeten we eerst een bestandssysteemindex maken.

Lucene biedt de FSDirectory class om een ​​bestandssysteemindex te maken:

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

Hier indexPath is de locatie van de directory. Als de directory niet bestaat, zal Lucene deze aanmaken.

Lucene biedt drie concrete implementaties van het abstract FSDirectory klasse: SimpleFSDirectory, NIOFSDirectory en MMapDirectory. Elk van hen kan speciale problemen hebben met een bepaalde omgeving.

Bijvoorbeeld, SimpleFSDirectory heeft slechte gelijktijdige prestaties omdat het blokkeert wanneer meerdere threads uit hetzelfde bestand worden gelezen.

Evenzo is het NIOFSDirectory en MMapDirectory implementaties worden geconfronteerd met respectievelijk problemen met bestandskanalen in Windows en problemen met het vrijgeven van geheugen.

Om dergelijke omgevingskenmerken te overwinnen, biedt Lucene de FSDirectory.open () methode. Wanneer het wordt aangeroepen, probeert het de beste implementatie te kiezen, afhankelijk van de omgeving.

4. Index-tekstbestand

Nadat we de indexdirectory hebben gemaakt, gaan we door en voegen we een bestand toe aan de index:

public void addFileToIndex (String bestandspad) {Padpad = Paths.get (bestandspad); Bestandsbestand = path.toFile (); IndexWriterConfig indexWriterConfig = nieuwe IndexWriterConfig (analyzer); Directory indexDirectory = FSDirectory .open (Paths.get (indexPath)); IndexWriter indexWriter = nieuwe IndexWriter (indexDirectory, indexWriterConfig); Document document = nieuw document (); FileReader fileReader = nieuwe FileReader (bestand); document.add (nieuw TextField ("inhoud", fileReader)); document.add (nieuw StringField ("pad", file.getPath (), Field.Store.YES)); document.add (nieuw StringField ("filename", file.getName (), Field.Store.YES)); indexWriter.addDocument (document); indexWriter.close (); }

Hier maken we een document met twee StringFields genaamd "pad" en "bestandsnaam" en een TextField genaamd "inhoud".

Merk op dat we de fileReader instantie als de tweede parameter voor de TextField. Het document wordt aan de index toegevoegd met de IndexWriter.

Het derde argument in de TextField of StringField constructor geeft aan of de waarde van het veld ook wordt opgeslagen.

Ten slotte roepen we de dichtbij() van de IndexWriter om de indexbestanden netjes te sluiten en op te heffen.

5. Zoek geïndexeerde bestanden

Laten we nu de bestanden zoeken die we hebben geïndexeerd:

openbare lijst searchFiles (String inField, String queryString) {Queryquery = nieuwe QueryParser (inField, analyzer) .parse (queryString); Directory indexDirectory = FSDirectory .open (Paths.get (indexPath)); IndexReader indexReader = DirectoryReader .open (indexDirectory); IndexSearcher-zoeker = nieuwe IndexSearcher (indexReader); TopDocs topDocs = searcher.search (zoekopdracht, 10); terug naar topDocs.scoreDocs.stream () .map (scoreDoc -> zoeker.doc (scoreDoc.doc)) .collect (Collectors.toList ()); }

Laten we nu de functionaliteit testen:

@Test openbare ongeldig gegevenSearchQueryWhenFetchedFileNamehenCorrect () {String indexPath = "/ tmp / index"; String dataPath = "/tmp/data/file1.txt"; Directory-directory = FSDirectory .open (Paths.get (indexPath)); LuceneFileSearch luceneFileSearch = nieuwe LuceneFileSearch (directory, nieuwe StandardAnalyzer ()); luceneFileSearch.addFileToIndex (dataPath); Lijst docs = luceneFileSearch .searchFiles ("inhoud", "consectetur"); assertEquals ("file1.txt", docs.get (0) .get ("filename")); }

Merk op hoe we een bestandssysteemindex op de locatie maken indexPath en het indexeren van de bestand1.txt.

Vervolgens zoeken we gewoon naar de Draadconsectetur" in de "inhoud" veld.

6. Conclusie

Dit artikel was een korte demonstratie van het indexeren en zoeken van tekst met Apache Lucene. Voor meer informatie over het indexeren, schroeien en vragen van Lucene, verwijzen wij u naar onze inleiding op het Lucene-artikel.

Zoals altijd is de code voor de voorbeelden te vinden op Github.