实现了Lucene和Tika 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”这样的单词时(假设有包含这些单词的文件),它不会向我返回任何内容。
答案 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);
您通常应该使用相同的分析器,索引和搜索时间(除非您有充分的理由不这样做)。