Este exemplo aborda uma forma simples de indexação e busca de documentos utilizando a API do Apache Lucene, na sua atual versão 3.6. Ela pode ser baixada aqui e para utilizar em seu projeto, basta incluir a lib lucene-core-3.6.0.jar em seu classpath.
Criando o índice e definindo os termos dos documentos:
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_36); FSDirectory indexDir = FSDirectory.open(new File("/index")); IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_36, analyzer); IndexWriter iw = new IndexWriter(indexDir, iwc); final String FIELD_LINK = "link"; final String FIELD_POST = "post";
Na primeira linha definimos qual será o analisador tanto para a indexação, quanto a que será utilizada no momento da busca. Neste caso utilizarei a Standard, mas já se tem disponível o analyzer em diversas linguagens e também pode-se criar um próprio, se necessário.
Após é feito a criação e abertura do índice. Neste caso, utilizando um índice gravado em disco através da classe FSDirectory. Dependendo da necessidade, pode-se usar a classe RAMDirectory para trabalhar com o índice todo somente em memória.
FIELD_LINK e FIELD_POST são os dois campos de exemplos deste índice, indicando o link de uma página e o seu conteúdo, respectivamente.
Inserindo um documento no índice:
Document doc1 = new Document(); doc1.add(new Field(FIELD_LINK, "http://www.coffeecode.com.br/?doc=1", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS)); doc1.add(new Field(FIELD_POST, "teste de busca em um texto livre", Field.Store.YES, Field.Index.ANALYZED)); iw.addDocument(doc1); Document doc2 = new Document(); doc2.add(new Field(FIELD_LINK, "http://www.coffeecode.com.br/?doc=2", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS)); doc2.add(new Field(FIELD_POST, "outro texto para busca", Field.Store.YES, Field.Index.ANALYZED)); iw.addDocument(doc2); iw.commit();
O Lucene trabalha com documentos, então cada entrada de dados será um documento com seus campos. Assim, instanciamos a classe Document e definimos quais serão seus campos, o valor, se este valor será recuperado ou apenas buscável e se ele deve passar pelo analisador.
Feito isto, os dois documentos já estão indexados e prontos para serem buscados. Sendo assim, partimos para a busca!
IndexReader ir = IndexReader.open(indexDir); IndexSearcher is = new IndexSearcher(ir); PhraseQuery pq = new PhraseQuery(); pq.add(new Term(FIELD_POST, "livre")); TopDocs td = is.search(pq, 10); for(ScoreDoc sdoc : td.scoreDocs) { Document d = is.doc(sdoc.doc); System.out.println("Link: "+d.get(FIELD_LINK)); System.out.println("Post: "+d.get(FIELD_POST)); }
Com a classe IndexReader deixamos disponível o índice para leitura e utilizamos a IndexSearcher para passar a query e recuperar os documentos. Aqui podemos usar diversos tipos de implementações da classe Query, como a PhraseQuery, BooleanQuery, MultiPhraseQuery, TermQuery, entre outras.
A busca, neste caso, será pela palavra “livre” em cima do campo indexado post. Ela pode retornar um objeto TopDocs que contém os documentos que bateram com o termo buscado. A partir deles pode-se acessar diretamente o índice e retornar os campos desejados.