2009-01-24 21 views
11

Estoy desarrollando un motor de búsqueda de escritorio en Visual Basic 9 (VS2008) usando Lucene.NET (v2.0).¿Cómo actualizar un índice Lucene.NET?

uso el siguiente código para inicializar el IndexWriter

Private writer As IndexWriter 

writer = New IndexWriter(indexDirectory, New StandardAnalyzer(), False) 

writer.SetUseCompoundFile(True) 

Si selecciono la misma carpeta de documentos (que contiene los archivos para ser indexados) dos veces, dos entradas diferentes para cada archivo en la carpeta de documentos se crean en el índice.

Quiero que IndexWriter descarte cualquier archivo que ya esté presente en el índice.

¿Qué debo hacer para asegurar esto?

+0

¿Estás tratando de reconstruir el índice de cero cada vez, o está intentando actualizar entradas específicas en el índice? Por favor aclara tu pregunta. – itsadok

Respuesta

4

Para actualizar un índice lucene, necesita eliminar la entrada anterior y escribir en la nueva entrada. Por lo tanto, debe usar un IndexReader para buscar el elemento actual, usar el escritor para eliminarlo y luego agregar su nuevo elemento. Lo mismo sucederá con las entradas múltiples, que creo que es lo que está tratando de hacer. Solo encuentre todas las entradas, elimínelas todas y luego escriba las nuevas entradas.

+0

¿Podría indicarme una demostración que muestra el uso de IndexReader (para encontrar el elemento actual y) para actualizar el índice? – user57175

+0

Esto parece provocar que falten documentos cuando vuelva a enviar la búsqueda – JsonStatham

5

Si desea eliminar todo el contenido del índice de y volver a llenarlo, se puede utilizar esta declaración

writer = New IndexWriter(indexDirectory, New StandardAnalyzer(), True) 

El último parámetro de la IndexWriter constructor determina si se crea un nuevo índice, o si una ya existente el índice se abre para agregar nuevos documentos.

+1

respuesta más simple al índice de borrado durante la reconstrucción, thx – jcvandan

19

Como mencionó Steve, necesita usar una instancia de IndexReader y llamar a su método DeleteDocuments. DeleteDocuments acepta ya sea una instancia de un objeto Término o el id. Interno de Lucene del documento (generalmente no se recomienda usar el Id. Interno como puede y cambiará cuando Lucene fusione segmentos).

La mejor manera es utilizar un identificador único que haya almacenado en el índice específico de su aplicación. Por ejemplo, en un índice de pacientes en un consultorio médico, si tiene un campo llamado "patient_id", puede crear un término y pasarlo como argumento para DeleteDocuments. Véase el siguiente ejemplo (lo siento, C#):

int patientID = 12; 
IndexReader indexReader = IndexReader.Open(indexDirectory); 
indexReader.DeleteDocuments(new Term("patient_id", patientID)); 

Entonces se puede inscribir el registro del paciente de nuevo con una instancia de IndexWriter. Aprendí mucho de este artículo http://www.codeproject.com/KB/library/IntroducingLucene.aspx.

Espero que esto ayude.

3

A menos que solo esté modificando una pequeña cantidad de documentos (por ejemplo, menos del 10% del total) es casi seguro más rápido (su kilometraje puede variar según los campos almacenados/indexados, etc.) para reindexar desde cero.

Dicho esto, siempre indexaría un directorio temporal, y luego movería el nuevo en su lugar cuando lo haya hecho. De esta forma, hay poco tiempo de inactividad mientras se construye el índice, y si algo sale mal, aún tiene un buen índice.

11

Hay muchos ejemplos desactualizados al eliminar con un campo de id. El siguiente código funcionará con Lucene.NET 2.4.

No es necesario abrir un IndexReader si ya está utilizando un IndexWriter o para acceder a IndexSearcher.Reader. Puede usar IndexWriter.DeleteDocuments (Término), pero la parte difícil es asegurarse de que haya almacenado su campo de identificación correctamente en primer lugar. Asegúrese y use Field.Index.NOT_ANALYZED como la configuración de índice en su campo de identificación al almacenar el documento. Este indexa el campo sin tokenizar, lo cual es muy importante, y ninguno de los otros valores Field.Index funcionará cuando se usa de esta manera:

IndexWriter writer = new IndexWriter("\MyIndexFolder", new StandardAnalyzer()); 
var doc = new Document(); 
var idField = new Field("id", "MyItemId", Field.Store.YES, Field.Index.NOT_ANALYZED); 
doc.Add(idField); 
writer.AddDocument(doc); 
writer.Commit(); 

Ahora se puede borrar o actualizar el documento utilizando el mismo escritor fácilmente:

Term idTerm = new Term("id", "MyItemId"); 
writer.DeleteDocuments(idTerm); 
writer.Commit(); 
+1

Incluso esa firma para IndexWriter ahora está obsoleta (y se eliminará en Lucene 3.0). El ctor sugerido sería el nuevo IndexWriter (directorio, analizador, maxFieldLength) y para el analizador, nuevamente la firma está obsoleta. El sugerido es el nuevo StandardAnalyzer (Version). – autonomatt

2

una opción es, por supuesto, para eliminar un documento y luego añadir la versión actualizada del documento.

Alternativamente, también puede utilizar el método updateDocument() de la clase IndexWriter:

writer.UpdateDocument(new Term("patient_id", document.Get("patient_id")), document); 

Por supuesto, esto requiere tener un mecanismo por el cual se puede localizar el documento que desea actualizar ("Patient_ID" en este ejemplo).

Tengo blogged more details with a more complete source code example.

4

Hay opciones, enumeradas a continuación, que se pueden usar según los requisitos.

Vea el siguiente fragmento de código. [El código fuente en C#, por favor, convertirlo en vb.net]

Lucene.Net.Documents.Document doc = ConvertToLuceneDocument(id, data); 
Lucene.Net.Store.Directory dir = Lucene.Net.Store.FSDirectory.Open(new DirectoryInfo(UpdateConfiguration.IndexTextFiles)); 
Lucene.Net.Analysis.Analyzer analyzer = new Lucene.Net.Analysis.Standard.StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29); 
Lucene.Net.Index.IndexWriter indexWriter = new Lucene.Net.Index.IndexWriter(dir, analyzer, false, Lucene.Net.Index.IndexWriter.MaxFieldLength.UNLIMITED); 
Lucene.Net.Index.Term idTerm = new Lucene.Net.Index.Term("id", id); 

foreach (FileInfo file in new DirectoryInfo(UpdateConfiguration.UpdatePath).EnumerateFiles()) 
{ 
     Scenario 1: Single step update. 
       indexWriter.UpdateDocument(idTerm, doc, analyzer); 

     Scenario 2: Delete a document and then Update the document 
       indexWriter.DeleteDocuments(idTerm); 
       indexWriter.AddDocument(doc); 

     Scenario 3: Take necessary steps if a document does not exist. 

      Lucene.Net.Index.IndexReader iReader = Lucene.Net.Index.IndexReader.Open(indexWriter.GetDirectory(), true); 
      Lucene.Net.Search.IndexSearcher iSearcher = new Lucene.Net.Search.IndexSearcher(iReader); 
      int docCount = iSearcher.DocFreq(idTerm); 
      iSearcher.Close(); 
      iReader.Close(); 
      if (docCount == 0) 
      { 
        //TODO: Take necessary steps 
        //Possible Step 1: add document 
        //indexWriter.AddDocument(doc); 

        //Possible Step 2: raise the error for the unknown document 
      } 
} 
indexWriter.Optimize(); 
indexWriter.Close(); 
Cuestiones relacionadas