Atualmente existem
diversas características dos bancos NOSQL, em diferentes
arquiteturas, formas de armazenamento de informação e estruturas de
dados. No entanto apesar dessa grande variedade no número e
variedades eles compartilham uma coisa em comum. Eles normalmente
buscam pela chave primária. Apesar de conseguir-se manter altamente
disponível, inserir e recuperar informações de forma bastante
rápida, o fato de que a maioria dos bancos NOSQL somente recuperem
pela chave, torna um pouco difícil adaptar a aplicação para o seu
uso, já que nem sempre você consegue buscar apenas pela chave no banco.
Para não abrir mão da alta disponibilidade e recuperar informações
não apenas em chave, uma boa opção certamente é “terceirizar”
esse serviço. Por esse motivo será apresentado o Lucene trabalhando
em conjunto com um banco nosql, mais precisamente o Cassandra,
juntando o bom de dois mundos em sua aplicação.
O Apache Lucene é uma API de busca e indexação de documentos,
escrito em Java. Ele é composto por basicamente duas etapas:
indexação e pesquisa. Dado o texto primeiro passo é a indexação
que processa os dados originais e gera uma estrutura que facilita a
busca e gera palavras-chaves, em seguida vem à busca que visa estar
buscando a partir das palavras-chaves indexadas e retorna pela
semelhança do texto com a consulta. A vantagem é que o Lucene
abstrai ao ponto que não é necessário que o desenvolvedor saiba
algoritmo de indexação. Os índices podem ser criados em ambientes
distribuídos, aumentando o desempenho e a escalabilidade da
ferramenta.
Apresentado um pouco da ferramenta o objetivo agora será apresentar
uma prática envolvendo os dois mundos: banco nosql e o Lucene. Para
essa parte prática será feita uma aplicação com o objetivo de
estar cadastrando currículos. A idéia é bastante simples:
- O usuário estará cadastrando o currículo com suas informações.
- A partir dessas informações a analista de recursos humanos estará buscando o profissional.
- O profissional poderá ser buscado pela palavra chave de uma qualificação técnica, localização, Profissão.
Como o objetivo da aplicação será web, estaremos utilizando a
plataforma Java EE em sua versão mais recente, a versão 6.0.
No Lucene os índices são armazenados a partir da interface Direcoty
que no momento que eu escrevo possui basicamente duas implementações:
Uma para armazenar na memória RAM e para armazenar no disco rígido.
Como o objetivo é garantir uma alta disponibilidade estaremos
utilizando a opção de estar trabalhando com os índices na memória
RAM, mas para não perdemos tais índices estaremos fazendo um backup
no disco rígido. Para fazer tal procedimento, usaremos o recurso
schedule do EJB 3.1 para de tempos em temos, jogar o que está na
memória para o HD.
Desse modo quando a aplicação cair e levantar novamente basta estar carregando as informações do disco para a memória principal novamente. Vale salientar que o diretório precisar único para toda a aplicação.
@Schedule(minute = "*/1", hour = "*") public void reindex() { try { Directory disco = FSDirectory.open(new File(Constantes.getIndexDirectory())); luceneManager.backup(directory, disco); } catch (Exception e) { Logger.getLogger(ScheduleService.class.getName()).log(Level.SEVERE, null, e); } }
@ApplicationScoped public class LuceneManager implements Serializable{ private static final long serialVersionUID = -8280220793266559394L; @Produces private Directory directory; @Inject public void init() { directory = new RAMDirectory(); try { levantarServico(); } catch (IOException e) { Logger.getLogger(LuceneManager.class.getName()).log(Level.SEVERE, null, e); } } public void levantarServico() throws IOException { Directory disco = FSDirectory.open(new File(Constantes.getIndexDirectory())); backup(disco, directory); } public void backup(Directory deDiretorio, Directory paraDiretoria) throws IOException { for (String file : deDiretorio.listAll()) { deDiretorio.copy(paraDiretoria, file, file); // newFile can be either file, or a new name } } }Uma vez criado o diretório e definido onde estarão as informações o próximo passo é criar os índices, conforme falado anteriormente ele será a chave tanto para a inserção quando a busca das informações. Agora o que falta é a criação do Document que representa para a troca de informações entre o Lucene e sua aplicação. Ele é composto por campos que por sua vez por informações. A relação entre o Lucene e a aplicação se dará da seguinte forma:
- A chave será armazenada e não indexada.
- O estado não armazenado e não indexado.
- O conteúdo do currículo será não armazenado e indexado.
private Document criarDocumento(Pessoa pessoa) throws IOException { Document document = new Document(); document.add(new Field(Constantes.ESTADO_INDICE,pessoa.getEndereco().getEstado(), Store.YES, Index.NOT_ANALYZED_NO_NORMS)); document.add(new Field(Constantes.ID_INDICE,pessoa.getNickName(), Store.YES, Index.NOT_ANALYZED_NO_NORMS,TermVector.WITH_POSITIONS_OFFSETS)); document.add(new Field(Constantes.TUDO, getConteudoCurriculo(pessoa), Store.NO, Index.ANALYZED)); return document; }
Uma vez essa informação armazenada no Cassandra e indexada no
Lucene, o ciclo da aplicação se dará da seguinte forma:
- A seqüência segue um processo simples:
- O usuário adiciona as informações e envia ao servidor
- A informação é persistida no Cassandra
- A informação é indexada e é armazenado o id no Lucene
Pronto! Dessa forma quanto a inserção quanto a busca serão feitas de maneiras rápidas, o Cassandra possui o recurso de índices secundários que permite que existam campos de busca além da chave, mas isso faz com que o banco perca velocidade com o crescimento desses campos especiais. Uma outra forma de deixar a busca ainda mais rápida seria deixar os resultados dessa busca em um cachê, mas isso serão cenas para um próximo capítulo.
Falando um pouco mais sobre o Lucene existem alguns frameworks que já
se integram com o Lucene. É o caso do hibernate search que é o
hiberante, para banco relacional, utilizando o Lucene, solr é um
servidor de busca que usa o Lucene como motor de busca e o solandra
que é um solr para o Cassandra.
Nesse artigo foi apresentado um problema existente na maioria dos
bancos NOSQL, a busca de campos além da chave. Para resolver tal
problema foi demonstrado um trabalho em conjunto com o Lucene,
ferramenta de indexação de documentos, além de apresentar alguns
conceitos da ferramenta.
Referências:
Referências:
Pamplona, Vitor.
http://vitorpamplona.com/wiki/Introdu%C3%A7%C3%A3o%20ao%20Apache%20Lucene
Hibernate
Search: http://www.hibernate.org/subprojects/search.html
Conhecendo o Lucene, PAULO SIGRIST e WILSON AKIO HIGASHINO, java Magazine 104, devmedia.
Código Fonte: http://softwarelivre.org/otagonsan/codigofonte/cassandra-lucene.rar
Código Fonte: http://softwarelivre.org/otagonsan/codigofonte/cassandra-lucene.rar
Este comentário foi removido pelo autor.
ResponderExcluir