无法返回Lucene + Tika上带重音的单词的结果

时间:2014-07-18 13:00:24

标签: java lucene apache-tika

实现了LuceneTika Apache库包,并设法使其能够很好地满足我的需求。但是我的单词重音有问题,它不能返回带重音的单词的结果。

Indexador.java

package br.com.ir;

import org.apache.log4j.Logger;
import org.apache.lucene.analysis.br.BrazilianAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.SimpleFSDirectory;
import org.apache.lucene.util.Version;
import org.apache.tika.Tika;

import javax.swing.*;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.text.SimpleDateFormat;

class Indexador {
    private static final Logger logger = Logger.getLogger(Indexador.class);
    private IndexWriter writer;
    private Tika tika;
    private int qntArq = 0;

    public void iniciaIndexacao() {
        try {
            File diretorio = new File(ArquivoDeConfiguracao.retornaValorIndice());

            apagaIndices(diretorio);

            Directory d = new SimpleFSDirectory(diretorio);

            BrazilianAnalyzer analyzer = new BrazilianAnalyzer(Version.LUCENE_4_9);

            IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_9,
                    analyzer);

            writer = new IndexWriter(d, config);

            long inicio = System.currentTimeMillis();
            indexaArquivosDoDiretorio(new File(ArquivoDeConfiguracao.retornaValorFonte()));
            // Fecha o IndexWriter e comita as mudanças
            writer.commit();
            long fim = System.currentTimeMillis();
            JOptionPane.showMessageDialog(
                    null,
                    "Quantidade de arquivos indexados: " + qntArq + "\n"
                            + "Tempo para indexar: "
                            + String.valueOf((fim - inicio) / 1000) + "s"
            );
        } catch (IOException e) {
            logger.error(e);
        } finally {
            if (writer != null) try {
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

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

    void indexaArquivosDoDiretorio(File raiz) {
        FilenameFilter filtro = new FilenameFilter() {
            public boolean accept(File arquivo, String nome) {
                return 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(".xlsx")
                        || nome.toLowerCase().endsWith(".txt")
                        || nome.toLowerCase().endsWith(".rtf")
                        || nome.toLowerCase().endsWith("");
            }
        };

        for (File arquivo : raiz.listFiles(filtro)) {
            if (arquivo.isFile()) {
                try {
                    String textoExtraido = getTika().parseToString(arquivo);
                    indexaArquivo(arquivo, textoExtraido);
                    qntArq++;
                } catch (Exception e) {
                    logger.error(e);
                }
            } else {
                indexaArquivosDoDiretorio(arquivo);
            }
        }
    }

    private void indexaArquivo(File arquivo, String textoExtraido) {
        SimpleDateFormat formatador = new SimpleDateFormat("ddMMyyyy");

        String ultimaModificacao = formatador.format(arquivo.lastModified());
        Document documento = new Document();
        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));

        try {
            getWriter().addDocument(documento);
        } catch (IOException e) {
            logger.error(e);
        }
    }

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

    IndexWriter getWriter() {
        return writer;
    }
}

Buscador.java

package br.com.ir;

import org.apache.log4j.Logger;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.SimpleFSDirectory;
import org.apache.lucene.util.Version;

import javax.swing.*;
import java.io.File;

class Buscador {
    private final static Logger logger = Logger.getLogger(Buscador.class);
    public int totalDeOcorrencias;
    public String quantBusca;

    @SuppressWarnings({"unchecked", "rawtypes"})
    public Buscador(String parametro, DefaultListModel listModel) {
        try {
            Directory diretorio = new SimpleFSDirectory(new File(
                    ArquivoDeConfiguracao.retornaValorIndice()));
            // 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_4_9);
            // QueryParser/Query: representa a consulta do usuário. Outros
            // exemplos de query podem ser vistos no Javadoc;
            QueryParser parser = new QueryParser(Version.LUCENE_4_9, "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();
            totalDeOcorrencias = resultado.totalHits;
            quantBusca = String.valueOf((fim - inicio) / 1000);

            // ScoreDoc: representa cada um dos documentos retornados na busca.
            for (ScoreDoc sd : resultado.scoreDocs) {
                Document documento = buscador.doc(sd.doc);
                // Preenche o modelo
                listModel.addElement(documento.get("Caminho"));
            }
            leitor.close();
        } catch (Exception e) {
            logger.error(e);
        }
    }
}

Indexador.java是在目录中搜索文件并将其索引到文件中的类。然后使用Buscador.java我执行搜索,但是当我尝试搜索像“plástico”ou“coração”这样的单词时(假设有包含这些单词的文件),它不会向我返回任何内容。

1 个答案:

答案 0 :(得分:4)

你在索引时使用BrazilianAnalyzer,我认为,它对重音词(以及词干分析词)有一些特定的处理,你在查询时使用StandardAnalyzer,这不是有那些语言特定的增强功能。

要解决此问题,请使用相同的分析器。可能BrazilianAnalyzer是您想去的方式,因此,在Buscador.java中,请更改为:

Analyzer analisador = new BrazilianAnalyzer(Version.LUCENE_4_9);
QueryParser parser = new QueryParser(Version.LUCENE_4_9, "Texto", analisador);

您通常应该使用相同的分析器,索引和搜索时间(除非您有充分的理由不这样做)。