java – How to index and search files in Lucene

Question:

I'm trying to generate a Java file indexer with Lucene's help.
I followed this iMasters guide and tried to adapt it to version 4.7.0 , the problem is that at some point the search is not working.
I have checked the index file and both the file information and its content are being indexed.
Could they help me?

Here's my code:

Indexador.java

package main;

import java.io.*;
import java.text.*;

import org.apache.log4j.*;
import org.apache.lucene.analysis.*;
import org.apache.lucene.analysis.standard.*;
import org.apache.lucene.document.*;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.*;
import org.apache.lucene.store.*;
import org.apache.lucene.util.*;
import org.apache.tika.*;

public class Indexador {
    private static Logger logger = Logger.getLogger(Indexador.class);
    // Diretório que irá guardar o índice;
    private String diretorioDosIndices = "C:\\Users\\strokes"
            + "\\Documents\\indice-lucene";
    // Diretório que contém os documentos que serão indexados;
    private String diretorioParaIndexar = "C:\\Users\\strokes"
            + "\\Downloads";
    // IndexWriter: cria e mantém o índice;
    private IndexWriter writer;
    // Biblioteca que extrai texto de diversos formatos conhecidos;
    private Tika tika;

    public static void main(String[] args) {
        Indexador indexador = new Indexador();
        indexador.indexaArquivosDoDiretorio();
    }

    public void indexaArquivosDoDiretorio() {
        try {
            File diretorio = new File(diretorioDosIndices);
            apagaIndices(diretorio);
            // Directory: representa o diretório do índice;
            Directory d = new SimpleFSDirectory(diretorio);
            logger.info("Diretório do índice: " + diretorioDosIndices);
            // Analyser/StandardAnalyser: fazem o pré-processamento do texto.
            // Existem analisadores inclusive em português;
            Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_47);
            // IndexWriterConfig: configurações para criação do índice. No
            // projeto serão utilizados os valores padrão;
            IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_47,
                    analyzer);
            // Inicializa o IndexWriter para gravação;
            writer = new IndexWriter(d, config);
            long inicio = System.currentTimeMillis();
            indexaArquivosDoDiretorio(new File(diretorioParaIndexar));
            // {12}
            writer.commit();
            writer.close();
            long fim = System.currentTimeMillis();
            logger.info("Tempo para indexar: " + ((fim - inicio) / 1000) + "s");
        } catch (IOException e) {
            logger.error(e);
        }
    }

    private void apagaIndices(File diretorio) {
        if (diretorio.exists()) {
            File arquivos[] = diretorio.listFiles();
            for (File arquivo : arquivos) {
                arquivo.delete();
            }
        }
    }

    public void indexaArquivosDoDiretorio(File raiz) {
        FilenameFilter filtro = new FilenameFilter() {
            public boolean accept(File arquivo, String nome) {
                if (nome.toLowerCase().endsWith(".pdf")
                        || nome.toLowerCase().endsWith(".odt")
                        || nome.toLowerCase().endsWith(".doc")
                        || nome.toLowerCase().endsWith(".docx")
                        || nome.toLowerCase().endsWith(".ppt")
                        || nome.toLowerCase().endsWith(".pptx")
                        || nome.toLowerCase().endsWith(".xls")
                        || nome.toLowerCase().endsWith(".txt")
                        || nome.toLowerCase().endsWith(".rtf")) {
                    return true;
                }
                return false;
            }
        };
        for (File arquivo : raiz.listFiles(filtro)) {
            if (arquivo.isFile()) {
                StringBuffer msg = new StringBuffer();
                msg.append("Indexando o arquivo ");
                msg.append(arquivo.getAbsoluteFile());
                msg.append(", ");
                msg.append(arquivo.length() / 1000);
                msg.append("kb");
                logger.info(msg);
                try {
                    // Extrai o conteúdo do arquivo com o Tika;
                    String textoExtraido = getTika().parseToString(arquivo);
                    indexaArquivo(arquivo, textoExtraido);
                } catch (Exception e) {
                    logger.error(e);
                }
            } else {
                indexaArquivosDoDiretorio(arquivo);
            }
        }
    }

    private void indexaArquivo(File arquivo, String textoExtraido) {
        SimpleDateFormat formatador = new SimpleDateFormat("yyyyMMdd");
        String ultimaModificacao = formatador.format(arquivo.lastModified());
        // Monta um Document para indexação
        // Field.Store.YES: armazena uma cópia do texto no índice, aumentando
        // muito o seu tamanho;
        // Field.Index.ANALYZED: utilizado quando o campo é de texto livre;
        // Field.Index.NOT_ANALYZED: utilizado quando o campo é um ID, data ou
        // númerico.
        Document documento = new Document();
        documento.add(new StringField("UltimaModificacao", ultimaModificacao, Field.Store.YES));
        documento.add(new StringField("Caminho", arquivo.getAbsolutePath(), Field.Store.YES));
        documento.add(new StringField("Texto", textoExtraido, Field.Store.YES));
        try {
            // Adiciona o Document no índice, mas este só estará disponível para
            // consulta após o commit.
            getWriter().addDocument(documento);
        } catch (IOException e) {
            logger.error(e);
        }
    }

    public Tika getTika() {
        if (tika == null) {
            tika = new Tika();
        }
        return tika;
    }

    public IndexWriter getWriter() {
        return writer;
    }
}

Buscador.java

package main;

import java.io.*;

import javax.swing.*;

import org.apache.log4j.*;
import org.apache.lucene.analysis.*;
import org.apache.lucene.analysis.standard.*;
import org.apache.lucene.document.*;
import org.apache.lucene.index.*;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.store.*;
import org.apache.lucene.util.*;

public class Buscador {
    private static Logger logger = Logger.getLogger(Buscador.class);
    private String diretorioDoIndice = "C:\\Users\\strokes"
            + "\\Documents\\indice-lucene";

    public void buscaComParser(String parametro) {
        try {
            Directory diretorio = new SimpleFSDirectory(new File(
                    diretorioDoIndice));
            // IndexReader: classe abstrata responsável por acessar o índice;
            IndexReader leitor = DirectoryReader.open(diretorio);
            // IndexSearcher: implementa os métodos necessários para realizar
            // buscas em um índice;
            IndexSearcher buscador = new IndexSearcher(leitor);
            Analyzer analisador = new StandardAnalyzer(Version.LUCENE_47);
            // QueryParser/Query: representa a consulta do usuário. Outros
            // exemplos de query podem ser vistos no Javadoc;
            QueryParser parser = new QueryParser(Version.LUCENE_47, "Texto",
                    analisador);
            Query consulta = parser.parse(parametro);
            long inicio = System.currentTimeMillis();
            // Realiza a busca e armazena o resultado em um TopDocs;
            TopDocs resultado = buscador.search(consulta, 100);
            long fim = System.currentTimeMillis();
            int totalDeOcorrencias = resultado.totalHits;
            logger.info("Total de documentos encontrados:" + totalDeOcorrencias);
            logger.info("Tempo total para busca: " + (fim - inicio) + "ms");
            // ScoreDoc: representa cada um dos documentos retornados na busca.
            for (ScoreDoc sd : resultado.scoreDocs) {
                Document documento = buscador.doc(sd.doc);
                logger.info("Caminho:" + documento.get("Caminho"));
                logger.info("Última modificação:"
                        + documento.get("UltimaModificacao"));
                logger.info("Score:" + sd.score);
                logger.info("--------");
            }
        } catch (Exception e) {
            logger.error(e);
        }
    }

    public static void main(String[] args) {
        Buscador b = new Buscador();
        String parametro = JOptionPane.showInputDialog("Consulta");
        b.buscaComParser(parametro);
    }
}

Answer:

The "Text" Field is a StringField, which means it is not parsed, and all content will be indexed as a single token. It's effectively the same as, in Lucene 3.6, using KeywordAnalyzer, or setting the Field to Field.Index.NOT_ANALYZED. In Lucene 4.X, you should use TextField instead, which is the default field for textual content, and so be analyzed.

Source: Can't index and find files [Java, Lucene, Tika, Log4j]

Modified part of the code in Indexador.java:

documento.add(new StringField("UltimaModificacao", ultimaModificacao, Field.Store.YES));
documento.add(new StringField("Caminho", arquivo.getAbsolutePath(), Field.Store.YES));
documento.add(new StringField("Texto", textoExtraido, Field.Store.YES));

For:

documento.add(new TextField("UltimaModificacao", ultimaModificacao, Field.Store.YES));
documento.add(new TextField("Caminho", arquivo.getAbsolutePath(), Field.Store.YES));
documento.add(new TextField("Texto", textoExtraido, Field.Store.YES));
Scroll to Top