Pesquisar

quarta-feira, 23 de dezembro de 2009

Jpcsp - v0.4 lançado - Castelvania Dracula X Chronicles

JPCSP - O emulador do PSP feito em Java

A muito tempo não dou mais nenhuma contribuição no projeto Jpcsp mas não deixo de acompanhar o progresso do projeto. (Pra quem não sabe o que é o Jpcsp!) A última notícia foi mesmo um presente de natal, a versão 0.4 do Jpcsp foi lançada e já está disponível para download.

Sinto um pouco de orgulho por ter conseguido participar, efetivamente, e realizar um dos meus sonhos de moleque. (Criar um emulador :) )... agora deixando de conversa fiada segue alguns screenshots!

Castlevania - Dracula X Chronicles


Heatseeker


God of war (In menu)



Feliz Natal! ho ho ho - Veja mais notícias do Jpcsp ou os meus posts antigos sobre Jpcsp.

quinta-feira, 3 de dezembro de 2009

Adicione o recurso "você quis dizer" nas suas aplicações Java

SpellChecker - Uma extensão no Lucene

Continuando brincando com Lucene, no novo Lucene 3.0.0 encontrei uma pasta contrib na qual há libs diversas. Uma delas é o SpellChecker que lhe oferece recursos para que você implemente em suas aplicações java (web ou desktop) recursos como "Você quis dizer".

Recurso Você quis dizer

Imagine : Você é dono de uma loja virtual na qual é oferecido DVDs para venda. Um fanático pelo ator Arnold Schwarzenegger entra no sua loja e tem em mente comprar todos os DVDs desse ator (hoje, governador) a primeira ação do usuário é digitar o nome do ator no campo busca. Facilmente ele irá errar a digitação do nome, por exemplo digitando "arnold swuazeneger", e isso não deveria ser algo impeditivo para compra dos DVDs. Para esse problema bastaria a solução do tipo "Você quis dizer foo" implementada pelo Google Inc. no seu motor de busca. Você consegue esse mesmo, ou próximo, efeito em suas buscas utilizando uma das extensões do Lucene, chamada de SpellChecker. O exemplo-código abaixo é simples e demonstra como fazer isso.

Código


     Directory diretorioDicionario = new RAMDirectory();
//criação do diretório
SpellChecker sp = new SpellChecker(diretorioDicionario);
//instânciação do objeto SpellChecker
sp.indexDictionary(new PlainTextDictionary(new File("dicionario.txt")));
//indexação do Dictionary (há duas implementações).
String pesquisa = "arnold swuazeneger";
//seu termo pesquiado
int numeroDeSugestoes = 5;
//número de sugestões similares
String[] similares = sp.suggestSimilar(pesquisa, numeroDeSugestoes);
//as sugestões em si.

System.out.println("Seu Termo : " + pesquisa);
for (String palavra : similares) {
System.out.println("Você quis dizer: " + palavra);
}

pesquisa = "bava";
similares = sp.suggestSimilar(pesquisa, numeroDeSugestoes);
System.out.println("Seu Termo : " + pesquisa);
for (String palavra : similares) {
System.out.println("Você quis dizer: " + palavra);
}

Saída


Seu Termo : arnold swuazeneger
Você quis dizer: arnold schwarzenegger

Seu Termo : bava
Você quis dizer: java
Você quis dizer: lava
Você quis dizer: bala


Arquivo dicionario.txt:
arnold schwarzenegger
jean claude van damme
java
lava
bala

Conclusão

Nem sempre é tão difícil quanto parece, sempre há uma roda já pronta para seu problema. Você ainda pode ajustar a acurácia da pesquisa pelo método setAccuracy do SpellChecker. Claro que o uso do recurso em produção requer mais e mais atenção quanto ao diretório e o dicionário de busca. Baseado nos códigos acima, facilmente você consegue levar essa características para seus sistemas Java Web ( JSF - JavaServer Faces, Struts, JSP).

terça-feira, 1 de dezembro de 2009

Tutorial Apache Lucene 3.0.0 - motor de busca textual


Lucene um motor de busca textual

No dia 25 de novembro foi lançado a nova versão do motor de busca Lucene, a versão 3.0.0. Lucene é um framework de alta performance para busca textual feito em java. (há versões para php e .net também) Uma das características marcantes dele é a integração com Hadoop. (um framework para computação distribuida - que possui, dentre outros, um MapReduce e um sistema de arquivos distribuido HDFS)

Porque usar Lucene?

Imagine o seguinte cenário: Seu usuário deseja criar um modulo de gerenciamento de artigos e também expó-los na Internet. As informações do artigo são: título, autor e o contéudo. Normalmente cada artigo desse contém cerca de 1500 palavras e o usuário poderá buscar pelo conteudo desses artigos. Suponha que há 1 milhão e meio de artigos para serem cadastrados, o simples uso de um banco de dados e o operador LIKE '%palavra%' é inviável. E aí que entra um bom framework de busca textual, usá-lo passa ser a solução mais tranquila e viável. Além de trazer velocidade, também traz outras características nas buscas que dificilmente fariamos codificando tudo do zero.

Domain-Specific Language | Ubiquitous Language

Há vários termos usados na terminologia do framework, os principais são: Documento, Campo, Diretório, Indexador, Pesquisador, Analisador e Termo.

  • Documento - é o conjunto de dados que você deseja indexar, por ex. título, conteudo e autor formam o documento artigo, pode ser visto como um objeto no lucene é visto como Document.
  • Campo - é o dado, identificado, que pode ser analogo a um campo de uma tabela ou uma propriedade de um objeto no lucene é visto como Field.
  • Diretório - conceito abstrato que denota um local para guardar os índices no lucene é visto como uma interface Directory, que possui diversas implementações DbDirectory, FSDirectory, JEDirectory, RAMDirectory.
  • Indexador - é o responsável por indexar os documentos num diretorio no lucene é visto, geralmente, como IndexWriter.
  • Pesquisador - responsável por pesquisar uma Query no diretorio de índices, no lucene é visto como Searcher.
  • Analisador - atua como um filtro e faz uma pré-avaliação do que pode ser indexado ou não, no lucene há uma lista de vários analisadores.
  • Termo - pode ser visto como objeto que pode ser usado como parametro da pesquisa, composto pelo nome do campo e o valor a ser pesquisado, no lucene é visto como Term.

Como isso funciona?

A descrição a seguir é um resumo bem simplificado sobre o funcionamento de um motor de busca textual. A primeira fase, geralmente, é a indexação do documento, nessa fase o documento é analizado (por um Analizer que também já retira as stopwords) para posteriomente ser indexado.

Set stopWords = new HashSet();
stopWords.add("the");
stopWords.add("it");
stopWords.add("is");
IndexWriter writer = new IndexWriter(FSDirectory.open(INDEX_DIR),
new StandardAnalyzer(Version.LUCENE_CURRENT,
stopWords),
false,
IndexWriter.MaxFieldLength.LIMITED);


No Lucene você pode criar um índice usando o IndexWriter, a criação desse objeto envolve dizer onde será (ou está) o diretório dos índices, qual analizador você irá utilizar, se irá criar o indice e qual a quantidade máxima de campos.

O objetivo do indexador é indexar documentos, para tanto é necessário que haja documentos para serem indexados.
Document doc = new Document();
doc.add(new Field("nomedocampo", "valores a serem guardados", Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.add(new Field("camp1","valores a serem analisados tokenizados",Field.Store.YES, Field.Index.toIndex(true, true)));
writer.addDocument(doc);
É o objetivo final de todo processo de busca textual é mesmo a busca em si.
String valueToBeSearched = "red";
String index = "indexDir"; //dirotorio base do indice
IndexReader reader = IndexReader.open(FSDirectory.open(new File(index)), true); //indexador
Searcher searcher = new IndexSearcher(reader); //pesquisador
QueryParser parser = new QueryParser(Version.LUCENE_CURRENT, field, analyzer); //transoformador do texto em uma query
Query query = parser.parse(valueToBeSearched); //a consulta (query) em si
TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, false); //os melhores resultados
searcher.search(query, collector);
ScoreDoc[] hits = collector.topDocs().scoreDocs; //o conjunto de melhores documentos para a consulta

int maximo = hits.length;
Document doc = searcher.doc(hits[index].doc);
String valor = doc.get("nomeDoCampo");

Recursos na busca de documentos

Quando se faz uma pesquisa por documentos no Lucene podemos utilizar de alguns operadores (+, -, AND, NOT, OR, * e etc.) juntamente com o termo pesquisado ou apenas pesquisar uma frase completa.

Exemplo : termo
Consequência: Irá pesquisar a palavra "termo" nos documentos indexados.

Exemplo : termo OR palavra ( == termo palavra)
Consequência: Irá pesquisar "termo" ou "palavra" nos documentos indexados.

Exemplo : +termo +palavra ( == termo AND palavra)
Consequência: Irá pesquisar "termo" e "palavra" nos documentos indexados.

Exemplo : campo:termo
Consequência: Irá pesquisar "termo" no campo "campo" nos documentos indexados.

Exemplo : +homer +simpsons -house
Consequência: Irá pesquisar documentos que contenham homer e simpsons e não tenha house.

Exemplo : "termo exato"
Consequência: Irá pesquisar documentos que contenham exatamente "termo exato".

Exemplo :
java*
Consequência: Irá pesquisar documentos que contenham palavras que começem com java (javadb, javanet...).

Exemplo : java~
Consequência: Irá pesquisar documentos que contenham palavras similares a java como por ex. lava, jaba...

Finalizando tive as seguintes impressões sobre essa nova versão do Lucene.

Prós:
  • Maior facilidade para uso do framework, ex: criações de Fields estão bem mais fluentes.
  • Sensível otimização nos tempos de busca e indexação.

Contras:
  • Otimas ferramentas como luke ainda não tem suporte para a versão 3.0.0. (mas já há uma solicitação aberta para tal mudança.)
  • Muitas mudanças no core do framework; o que fez livros mais antigos quase perderem seu valor.

Referências