Академический Документы
Профессиональный Документы
Культура Документы
1 2
Juan Pablo Ramos Hernández , Giner Alor Hernández
1
Facultad de Informática, Universidad Autónoma de Sinaloa, prolongación Josefa Ortiz de
Domínguez Ciudad Universitaria, Culiacán, Sinaloa.
2
División de Estudios de Posgrado e Investigación, Instituto Tecnológico de Orizaba,
Avenida Oriente 9 No. 852 Col. Emiliano Zapata C. P. 94320, Orizaba, Veracruz.
E-mail: jpramoshernandez@gmail.com, galor@itorizaba.edu.mx
1 Introducción
Lucene es una novedosa herramienta que permite tanto la indización cómo la
búsqueda de documentos.
Creada bajo una metodología orientada a objetos e implementada completamente en
Java, no se trata de una aplicación que se descarga, instala y ejecuta sino de una API
flexible, a través de la cual se añaden, con esfuerzos de programación, capacidades de
indización y búsqueda a cualquier sistema que se esté desarrollando. [1]
Existen otras herramientas, aparte de Lucene, que permiten realizar la indización y
búsqueda de documentos pero dichas herramientas se utilizan para usos concretos, lo
que implica que el intentar adaptarlas a un proyecto específico sea una tarea realmente
difícil. La idea que engloba Lucene es completamente diferente, ya que su principal
ventaja es su flexibilidad, permite su utilización en cualquier sistema que lleve a cabo
procesos de indización o búsqueda. [1]
Lucene tiene versiones para otros lenguajes como Perl, C#, Ruby y C++.
Para entrar más a detalle en el siguiente apartado se tratan los orígenes de Lucene.
2 Historia de Lucene
El desarrollo y crecimiento masivo de las redes de computadoras y medios de
almacenamiento a lo largo de los últimos años, motiva la aparición de un creciente
interés por los sistemas de clasificación automática de documentos. [1]
Esta necesidad de búsqueda de datos en la web o en cualquier archivo que contenga
texto dio origen a Lucene, para implementarse en cualquier aplicación o sistema que
requiera un motor de búsqueda, en la figura 1 se muestra como una aplicación hace
uso de Lucene.
Estos sistemas realizan diferentes operaciones de clasificación basándose en el
análisis del contenido del texto de los documentos que procesan. La mayoría de las
técnicas de análisis y representación de documentos utilizadas en la actualidad en los
sistemas de clasificación, se basan en criterios fundamentalmente estadísticos,
centrados en frecuencias de aparición de términos en los documentos. [1]
Figura 1: Lucene primero que nada indiza los documentos o BD que contiene la aplicación
para que después a través de una consulta del usuario, Lucene busque en el índice y muestre los
resultados con éxito.
En este apartado, y puesto que indización y búsqueda son dos objetivos muy
generales, que abarcan multitud de aspectos, se definen y se detallan cada una de
ellos.
Cuando se requiere hacer uso de búsquedas dentro de una aplicación, rápido se viene
a la mente crear un programa que haga esto, es decir, que busque en todos los
archivos palabras o frases relacionadas, esto tendría fallas en el caso de archivos muy
grandes. Por eso es importante crear los índices, transformar el texto en un formato
donde la búsqueda sea más rápida, eliminando el proceso de exploración lento. Este
proceso de conversión es llamado indización y al archivo resultante se le llama índice.
Un índice separa las palabras el documento en campos y permite el acceso rápido a
los datos que fueron almacenados en el proceso de indizado. [2]
Las clases que se muestran a continuación son las principales durante el proceso de
indización, para ello se definen cada una de ellas y el uso que tienen en Lucene. [2]
! IndexWriter
! Directory
! Analyzer
! Document
! Field
4.2.1 IndexWriter
Es el componente central del proceso de indización. Esta clase crea índices y agrega
documentos a uno ya existente. IndexWriter es un objeto que permite acceder al
índice pero no leer o buscar en el.
4.2.2 Directory
4.2.3 Analyzer
Antes de indizar un documento este pasa por la clase Analyzer. Esta clase elimina del
documento palabras que no ayudan o distinguen un documento de otro como él, la,
en, una, entre otras. También convierte en las palabras a minúsculas para que las
búsquedas sean más exactas.
4.2.4 Document
4.2.5 Field
Cada documento contiene uno o más campos, en Lucene existen 4 métodos Field
diferentes:
1. Keyword: Se almacena y se indiza tal cual, no se analiza, se utiliza para los
campos que necesitan guardarse en el índice sin modificaciones como el
número de seguridad social, los sitios de internet, directorio donde se
encuentra el documento, entre otras.
2. UnIndexed: Se almacena pero nunca se usa en las búsquedas, como las llaves
primarias en una base de datos.
3. Text: el valor se analiza e indiza, el valor original también se almacena.
4. UnStored: Es la opuesta a UnIndexed. Se analiza e indiza, se utiliza para
todos los documentos de texto o sitios web donde solo se requiera guardar
titulo y contenido. [2]
Para llevar a cabo una búsqueda con Lucene es importante familiarizarse con las
siguientes clases: [2]
! IndexSearcher
! Term
! Query
! TermQuery
! Hits
4.3.1 IndexSearcher
4.3.2 Term
4.3.3 Query
Lucene tiene diferentes subclases de Query, la más utilizada es TermQuery por los
métodos que ella contiene. [2]
4.3.4 TermQuey
Es el tipo de Query mas básico soportada por Lucene, se utiliza para hacer coincidir
documentos que tienen valores específicos.
4.3.5 Hits
En este caso para compilar y ejecutar los siguientes ejemplos, es necesario descargar
el archivo .jar de la versión 1.4.3 de Lucene, además de contar con algún IDE
(Interfaz de Desarrollo) de Java en este caso se recomienda KawaPro versión 5.0, con
el compilador de Java jdk versión 1.4.
package uas;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.*;
import java.io.*;
import java.util.Date;
public class CreateIndice {
public static void main(String[] args) throws Exception {
File indexDir = new File(("c:\\indexdir");
IndexWriter writer;
writer = new IndexWriter(indexDir, null, true);
writer.close();
}
}
Una vez que se crea el índice, está listo para empezar a añadirle documentos. El
siguiente programa Indexer.java en la figura 4, indiza archivos con formato .txt, se
puede cambiar la extensión a .doc, .html, ppt, .xml, .rtf y funciona igual.
package uas;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.*;
import java.io.*;
import java.util.Date;
public class Indexer {
public static void main(String[] args) throws Exception {
File indexDir = new File("c:\\indexdir");
File dataDir = new File("c:\\datadir");
long start = new Date().getTime();
int numIndexed = index(indexDir, dataDir);
long end = new Date().getTime();
System.out.println("Se han indizado " + numIndexed + " archivos
en " + (end - start) + " milisegundos");
}
public static int index(File indexDir, File dataDir)
throws IOException {
if (!dataDir.exists() || !dataDir.isDirectory()) {
throw new IOException(dataDir
+ " no existe o no es un directorio ");
}
IndexWriter writer = new IndexWriter(indexDir, new
StandardAnalyzer(), true);
writer.setUseCompoundFile(false);
indexDirectory(writer, dataDir);
int numIndexed = writer.docCount();
writer.optimize();
writer.close();
return numIndexed;
}
private static void indexDirectory(IndexWriter writer, File dir)
throws IOException {
File[] files = dir.listFiles();
for (int i = 0; i < files.length; i++) {
File f = files[i];
if (f.isDirectory()) {
indexDirectory(writer, f); // recurse
} else if (f.getName().endsWith(".txt")) {
indexFile(writer, f);
}
}
}
private static void indexFile(IndexWriter writer, File f)
throws IOException {
if (f.isHidden() || !f.exists() || !f.canRead()) {
return;
}
System.out.println("Indizando " + f.getCanonicalPath());
Document doc = new Document();
doc.add(Field.Text("contents", new FileReader(f)));
doc.add(Field.Keyword("filename", f.getCanonicalPath()));
writer.addDocument(doc);
}
}
Figura 4: Ejemplo que muestra como se indizan los archivos de texto con Lucene.
package uas;
import org.apache.lucene.document.Document;
import org.apache.lucene.search.*;
import org.apache.lucene.store.*;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import java.io.File;
import java.util.Date;
public class Searcher {
public static void main(String[] args) throws Exception {
String[] argsv=new String[2];
argsv[0]=new String("c:\\indexdir");
argsv[1]=new String("lucene");
File indexDir = new File(argsv[0]);
String q = argsv[1];
if (!indexDir.exists() || !indexDir.isDirectory()) {
throw new Exception(indexDir + " no existe o no es un
directorio. ");
}
search(indexDir, q);
}
public static void search(File indexDir, String q)
throws Exception {
Directory fsDir = FSDirectory.getDirectory(indexDir, false);
IndexSearcher is = new IndexSearcher(fsDir);
Query query = QueryParser.parse(q, "contents",
new StandardAnalyzer());
long start = new Date().getTime();
Hits hits = is.search(query);
long end = new Date().getTime();
System.out.println ("Se han encontrado " + hits.length() +
" documento(s) (en " + (end - start) +
" millisegundos) relacionados con la palabra '" +
q + "' en los directorios: ");
for (int i = 0; i < hits.length(); i++) {
Document doc = hits.doc(i);
System.out.println(doc.get("filename"));
}
}
}
6. Estructura de un índice
En los ejemplos, si se checa el directorio del índice creado, se ve que hay varios
archivos que al principio parecen similares.
Estos son los archivos del índice en la figura 7 y tienen la siguiente estructura:
Deletetable
_1fyc.f1
_1fyc.f2
_1fyc.fdt
_1fyc.fdx
_1fyc.fnm
_1fyc.frq
_1fyc.prx
_1fyc.tii
_1fyc.tis
Segments
Figura 7: Muestra los archivos que se generan en la creación de un índice con Lucene, este
tipo de archivo se crea cuando se optimiza el índice.
Para optimizar un índice, uno tiene que llamar el método optimize() de la clase
IndexWriter. Cuando esto sucede, todos los documentos en memoria pasan al disco
duro y todos los segmentos del índice se combinan en un solo segmento, reduciendo
el número de archivos que se crean para el índice. [5]
Sin embargo, la optimización de un índice no ayuda a mejorar funcionamiento de la
indización de direcciones.
De hecho, la optimización de un índice durante el proceso de la indización de
direcciones retardará solamente las cosas. A pesar de esto, la optimización puede a
veces ser necesaria para guardar el número de archivos abiertos bajo control. Por
ejemplo, la optimización de un índice durante el proceso de la indización de
direcciones se puede necesitar en las situaciones donde buscar e indizar son
concurrentes, puesto que ambos procesos guardan su propio sistema de archivos
abiertos. Una buena regla es que si más documentos se agregan pronto al índice, se
debe evitar llamar el método optimize(). Por otra parte, si el índice no será modificado
por buen tiempo, y el índice se usa para la búsqueda solamente, se debe optimizar.
Eso reducirá el número de los segmentos (archivos en el disco duro), y por lo tanto
mejora funcionamiento de la búsqueda, entre menos sea el número de archivos que
Lucene tiene que abrir mientras se busca, más rápida es la búsqueda. En la siguiente
figura 8 se muestra el contenido de los archivos del índice. [5]
Figura 8: Esta imagen muestra el contenido de los archivos creados por el índice, el archivo
.fnm almacena los campos de los documentos, el archivo .tii contiene información acerca de
esos campos, es decir, nombre del campo y valor, el archivo .prq almacena el numero de
documento y la frecuencia de aparición, mientras que el archivo .prx contiene la posición donde
se encuentra.
Después de analizar la estructura de un índice y lo que almacena cada uno de sus
archivos; es importante también conocer otras tecnologías de recuperación de
información, en la siguiente sección se hace una comparativa de Lucene con otras
bibliotecas de funciones importantes.
Como sistema de Recuperación de Información, Lemur permite todas las etapas desde
la indización a la búsqueda de documentos.
Lemur aporta una poderosa API implementada en C++ y está diseñada para trabajar
en todos los sistemas operativos, permite la indización incremental e indiza atributos
de los documentos. [6]
7.2 Xapian
7.3 Terrier
8.1 cLucene
La API de cLucene es similar a Lucene. Esto significa que el código escrito en Java se
convierte fácilmente al lenguaje de programación C++. La desventaja es que cLucene
no sigue el código estándar de C++.
Sin embargo, debido al número de clases que se tienen que rediseñar, cLucene sigue
el código estándar de Java. Esto también permite que mucho del código sea
convertido usando macros y scripts. [2]
8.2 dotLucene
Está escrito en C#, dotLucene tiene una API que es casi idéntica a la de Lucene. Por
lo tanto, el código escrito en Lucene puede ser trasladado fácilmente a C#. Esta
compatibilidad también permite que los desarrolladores de .NET utilicen la
documentación para la versión de Java.
Mientras que en Java los nombres de los métodos comienzan con letras minúsculas,
en la versión de .Net los nombres de los métodos comienzan con mayúscula. [2]
8.3 pLucene
Es una herramienta directa de Lucene y reserva una API extensa. La única diferencia
obvia está en el estilo del código, el cual sigue el estándar para el manejo y estructura
de módulos, métodos y clases de Perl.
Aunque el API de pLucene se asemeja a la de Lucene, existen algunas diferencias,
según los desarrolladores de pLucene, Java utiliza enteros largos de 64 bits pero la
mayoría de las versiones de Perl utilizan 32 bits. [2]
8.4 Lupy
Para empezar a trabajar con esta aplicación web es necesario crear un índice para así
irle agregando los documentos indizados los cuales se les van a realizar las búsquedas
posteriores, en la siguiente figura 10 del lado izquierdo, crearemos el índice, esto es
necesario cuando vas a empezar a trabajar con la aplicación o también cuando quieres
borrar un índice anterior para crear un nuevo, asi se crean los segmentos, cuando
ocurra algún problema en el servidor solo hay que detenerlo ir al directorio donde
están los índices y borrarlos manualmente se vuelve a iniciar el servidor apache
tomcat y se crea el índice, el directorio que guarda los índices se encuentra
establecido por defecto en c:/indexdir, si se desea cambiar la ruta es necesario
modificar el archivo procesa.jsp.
Figura 10: Se muestra el resultado de la creación de un índice.
Figura 13: Muestra la búsqueda con Lucene el usuario proporciona la palabra(s), Lucene se
encarga de encontrar documentos relacionados a esa palabra.
11 Agradecimientos
12 Bibliografía
[1] Motor de búsqueda para un SRI con agrupamiento,
http://trevinca.ei.uvigo.es/~pcuesta/sm/practicas/Lucene.pdf, 28/Junio/2007.
[2] Otis Gospodnetic et.al., "Lucene in action", Manning, 2005, pp. 44, 45, 46,53, 54,
55, 56, 57, 58, 59, 349, 352, 353, 355.
[3] Indexación con Lucene,
http://www.sia.eui.upm.es/isa/lib/exe/fetch.php?id=asignaturas%3Aagentes_inteligent
es&cache=cache&media=asignaturas:licencias.pdf, 27/Junio/2007.
[4] Advanced Text Indexing with Lucene,
http://www.onjava.com/pub/a/onjava/2003/03/05/lucene.html, 15/Julio/2007.
[5] Advanced Text Indexing with Lucene,
http://www.onjava.com/pub/a/onjava/2003/03/05/lucene.html?page=2, 15/Julio/2007.
[6] The Lemur Toolkit Features, http://www.lemurproject.org/features.php,
11/Agosto/2007.
[7] Features, http://www.xapian.org/features.php, 11/Julio/2007.
[8] Terrier: TERabyte RetrIEveR (I),
http://www.ojobuscador.com/2006/08/04/terrier-terabyte-retriever-i/, 3/Agosto/2007.