2012-05-31 14 views
8
  1. Quando un nuovo elemento viene aggiunto in MySQL, deve essere indicizzato anche da Lucene.
  2. Quando un elemento esistente viene rimosso da MySQL, deve essere rimosso anche dall'indice di Lucene.

L'idea è di scrivere uno script che verrà chiamato ogni x minuti tramite uno scheduler (ad esempio un'attività CRON). Questo è un modo per tenere sincronizzati MySQL e Lucene. Quello che ho gestito fino ad ora:Indicizzare un database MySQL con Apache Lucene e tenerli sincronizzati

  1. Per ogni nuovo elemento aggiunto in MySQL, Lucene lo indicizza anche.
  2. Per ogni elemento già aggiunto in MySQL, Lucene non lo reindicizza (nessun elemento duplicato).

questo è il punto che vi chiedo un aiuto per gestire:

  1. Per ogni elemento aggiunto in precedenza che è stato poi rimosso da MySQL, Lucene dovrebbe anche unindex esso.

Ecco il codice che ho usato, che cerca di indicizzare una tabella di 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: questo codice è per le prove solo scopo, non c'è bisogno di dirmi come terribile è :)

EDIT:

una soluzione potrebbe essere quella di eliminare qualsiasi documento previsouly aggiunto e reindex tutto il database:

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); 
} 

Non sono sicuro che sia la soluzione più ottimizzata, vero?

+0

Cosa hai finito? –

risposta

7

Fintanto che l'indicizzazione/reindicizzazione viene eseguita separatamente dall'applicazione, si avranno problemi di sincronizzazione. A seconda del campo di lavoro, questo potrebbe non essere un problema, ma per molte applicazioni utente concorrenti lo è.

Abbiamo avuto gli stessi problemi quando avevamo un sistema di lavoro che eseguiva l'indicizzazione asincrona ogni pochi minuti. Gli utenti trovavano un prodotto utilizzando il motore di ricerca, quindi anche quando una persona amministrativa rimuoveva il prodotto dallo stack del prodotto valido, lo trovava ancora nel frontend, finché non veniva eseguito il successivo lavoro di reindicizzazione. Ciò porta a errori molto confusi e raramente riproducibili riportati al supporto di primo livello.

Abbiamo visto due possibilità: collegare strettamente la business logic agli aggiornamenti dell'indice di ricerca o implementare un task di aggiornamento asincrono più stretto. Abbiamo fatto quest'ultimo.

In background, c'è una classe in esecuzione in un thread dedicato all'interno dell'applicazione tomcat che prende gli aggiornamenti e li esegue in parallelo. I tempi di attesa per gli aggiornamenti del backoffice sul frontend sono ridotti a 0,5-2 secondi, il che riduce notevolmente i problemi per il supporto di primo livello. E, quanto meno accoppiato, possiamo addirittura implementare un motore di indicizzazione diverso.

1

Dai un'occhiata all'approccio Solr DataImportScheduler.
Fondamentalmente, quando viene avviata un'applicazione Web, genera un thread Timer separato, che periodicamente invia HTTP Post a Solr, che quindi utilizza DataImportHandler impostato per estrarre i dati da un RDB (e altre origini dati).

Quindi, dal momento che non stai usando Solr, solo Lucene, dovresti dare un'occhiata a DataImportHandler source per le idee.

Problemi correlati