2012-05-31 14 views
8
  1. Cuando se añade un nuevo elemento en MySQL, debe ser también un índice por Lucene.
  2. Cuando un elemento existente se elimina de MySQL, también debe eliminarse del índice de Lucene.

La idea es escribir un script que se llamará cada x minutos a través de un planificador (por ejemplo, una tarea CRON). Esta es una forma de mantener sincronizados MySQL y Lucene. Lo que logré hasta ahora:Índice de una base de datos MySQL con Apache Lucene, y mantenerlos sincronizados

  1. Por cada nuevo elemento añadido en MySQL, Lucene lo indexa también.
  2. Para cada elemento ya agregado en MySQL, Lucene no lo reindexa (no hay elementos duplicados).

Este es el punto que te pido un poco de ayuda para gestionar:

  1. Para cada elemento añadido previamente que se ha retirado luego de MySQL, Lucene también debe unindex ella.

Aquí está el código que utilicé, que trata de indexar una tabla de MySQL tag (id [PK] | name):

public static void main(String[] args) throws Exception { 

    Class.forName("com.mysql.jdbc.Driver").newInstance(); 
    Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/mydb", "root", ""); 
    StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_36); 
    IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_36, analyzer); 
    IndexWriter writer = new IndexWriter(FSDirectory.open(INDEX_DIR), config); 

    String query = "SELECT id, name FROM tag"; 
    Statement statement = connection.createStatement(); 
    ResultSet result = statement.executeQuery(query); 

    while (result.next()) { 
     Document document = new Document(); 
     document.add(new Field("id", result.getString("id"), Field.Store.YES, Field.Index.NOT_ANALYZED)); 
     document.add(new Field("name", result.getString("name"), Field.Store.NO, Field.Index.ANALYZED)); 
     writer.updateDocument(new Term("id", result.getString("id")), document); 
    } 

    writer.close(); 

} 

PS: este código es para propósitos pruebas solamente, no hay necesidad de que me diga lo terrible que es :)

EDIT:

Una solución podría ser la de eliminar cualquier documento añadido previsouly y indexar toda la base de datos:

writer.deleteAll(); 
while (result.next()) { 
    Document document = new Document(); 
    document.add(new Field("id", result.getString("id"), Field.Store.YES, Field.Index.NOT_ANALYZED)); 
    document.add(new Field("name", result.getString("name"), Field.Store.NO, Field.Index.ANALYZED)); 
    writer.addDocument(document); 
} 

No estoy seguro de que sea la solución más optimizada, ¿o sí?

+0

¿Qué terminaste haciendo? –

Respuesta

7

Siempre que permita que la indexación/reindexación se ejecute por separado de su aplicación, tendrá problemas de sincronización. Dependiendo de su campo de trabajo, esto podría no ser un problema, pero para muchas aplicaciones de usuarios simultáneos sí lo es.

Tuvimos los mismos problemas cuando teníamos un sistema de trabajo ejecutando indexación asincrónica cada pocos minutos. Los usuarios encontrarían un producto utilizando el motor de búsqueda, incluso cuando una persona administrativa eliminara el producto de la pila de productos válida, aún lo encontrara en la interfaz, hasta que se ejecutara el siguiente trabajo de reindexación. Esto lleva a errores muy confusos y rara vez reproducibles reportados al soporte de primer nivel.

Vimos dos posibilidades: conectar estrechamente la lógica empresarial a las actualizaciones del índice de búsqueda o implementar una tarea de actualización asíncrona más estricta. Hicimos lo último.

En el fondo, hay una clase ejecutándose en un subproceso dedicado dentro de la aplicación tomcat que toma actualizaciones y las ejecuta en paralelo. Los tiempos de espera para las actualizaciones de backoffice a frontend han bajado a 0.5-2 segundos, lo que reduce enormemente los problemas para el soporte de primer nivel. Y, si está lo más unido posible, podríamos incluso implementar un motor de indexación diferente.

1

Eche un vistazo al enfoque de Solr DataImportScheduler.
Básicamente, cuando se inicia una aplicación web, genera un subproceso Timer independiente, que periódicamente activa Post HTTP contra Solr, que luego utiliza DataImportHandler que configura para extraer datos de un RDB (y otras fuentes de datos).

Así que, ya que no está usando Solr, solo Lucene, debería echar un vistazo a DataImportHandler source para obtener ideas.

Cuestiones relacionadas