2010-01-21 8 views
6

Estoy escribiendo una aplicación interna que contiene varios fragmentos de información de texto, así como una cantidad de datos sobre estos fragmentos de texto. Estos datos se guardarán en una base de datos (SQL Server, aunque esto podría cambiar) por orden de entrada.Escribir un índice invertido en C# para una aplicación de recuperación de información

Me gustaría poder buscar la información más relevante de estas, con las más relevantes para estar en la parte superior. Originalmente investigué el uso de la búsqueda de texto completo de SQL Server pero no es tan flexible para mis otras necesidades como esperaba, así que parece que tendré que desarrollar mi propia solución para esto.

Por lo que entiendo, lo que se necesita es un inverted index, luego para que los contenidos de dicho índice invertido sean restaurados y modificados en base a los resultados de la información adicional (aunque por ahora esto puede dejarse para una fecha posterior Solo quiero que el índice invertido indexe el texto principal de la tabla/cadenas de la base de datos proporcionadas).

He tenido un gran problema al escribir este código en Java usando una Hashtable con la clave como las palabras y el valor como una lista de las apariciones de la palabra, pero honestamente todavía soy bastante nuevo en C# y solo han usado cosas realmente como DataSets y DataTables cuando manejan información. Si lo solicita, subiré el código de Java pronto una vez que haya borrado este portátil de virus.

Si se le da un conjunto de entradas de una tabla o de una Lista de cadenas, ¿cómo se puede crear un índice invertido en C# que preferiblemente se guardará en un DataSet/DataTable?

EDIT: Olvidé mencionar que ya he probado Lucene y Nutch, pero necesito mi propia solución ya que modificar Lucene para satisfacer mis necesidades tomaría mucho más tiempo que escribir un índice invertido. Manejaré una gran cantidad de metadatos que también necesitarán tratamiento una vez que se complete el índice invertido básico, por lo que todo lo que necesito por ahora es una búsqueda básica de texto completo en un área usando el índice invertido. Finalmente, trabajar en un índice invertido no es algo que deba hacer todos los días, así que sería genial tener una oportunidad.

+0

Aquí hay otro índice invertido de C# basado en genéricos: http://www.aleandmusic.com/InvertedIndex.aspx –

Respuesta

4

Aquí es una visión general de un enfoque que he usado con éxito en C# en el pasado:

struct WordInfo 
{ 
    public int position; 
    public int fieldID; 
} 

Dictionary<string,List<WordInfo>> invertedIndex=new Dictionary<string,List<WordInfo>>(); 

     public void BuildIndex() 
     { 
      foreach (int fieldID in GetDatabaseFieldIDS()) 
      {  
       string textField=GetDatabaseTextFieldForID(fieldID); 

       string word; 

       int position=0; 

       while(GetNextWord(textField,out word,ref position)==true) 
       { 
        WordInfo wi=new WordInfo(); 

        if (invertedIndex.TryGetValue(word,out wi)==false) 
        { 
         invertedIndex.Add(word,new List<WordInfo>()); 
        } 

        wi.Position=position; 
        wi.fieldID=fieldID; 
        invertedIndex[word].Add(wi); 

       } 

      } 
     } 

Notas:

GetNextWord() itera a través del campo y devuelve la siguiente palabra y la posición . Para implementarlo, observe el uso de los métodos de comprobación de caracteres string.IndexOf() y char (IsAlpha, etc.).

GetDatabaseTextFieldForID() y GetDatabaseFieldIDS() se explican por sí mismos, implementar según sea necesario.

+0

Disculpa la gran demora en volver a esta respuesta. ¡Esto se ve genial! La única pregunta que tengo con esto es cómo uno podría escribir su diccionario de nuevo en una base de datos. He editado la pregunta con lo que quiero decir. –

+0

Lo siento, acabo de revisar el código y me di cuenta de que podía simplemente duplicar las palabras si aparecían en más de un documento. Debería ser bastante fácil enviar esto a mi base de datos manejando clases; una vez que lo implemente, aceptaré esta respuesta. –

+0

@Ender, me alegro de que haya sido útil. La serialización es una opción para guardar/cargar desde las bases de datos. Alternativamente, iterar a través de la colección de claves del diccionario y obtener cada valor correspondiente sería otro. – Ash

2

Lucene.net podría ser su mejor apuesta. Es un motor de búsqueda de texto maduro con inverted indexes.

http://codeclimber.net.nz/archive/2009/09/02/lucene.net-your-first-application.aspx

ACTUALIZACIÓN:

escribí una pequeña biblioteca para la indexación en contra de las colecciones en memoria utilizando Lucene.net - que podría ser útil para esto. https://github.com/mcintyre321/Linqdex

+0

Debería haber explicado en mi pregunta que ya había examinado el uso de Lucene o el reemplazo de partes de su funcionalidad con qué He escrito. Lamentablemente, Lucene no es lo suficientemente flexible como para que yo pueda cambiar lo que necesito para cumplir los criterios de la información que necesito tener, así que tendré que escribir el índice invertido yo mismo. –

+0

Extrañamente, mi experiencia con Lucene.net es que es * demasiado * flexible, por lo que las tareas que deben ser simples son una tarea ardua. Además, no funciona bien en confianza media. Además, la filosofía de mantenerse fiel a Java significa que no se utilizan muchos modismos de C# /. NET convenientes y eficaces. Una pena porque es increíble en muchos sentidos. –

1

Si está buscando hacer su propio truco, es probable que la clase Dictionary<T> sea su base, como las tablas hash de Java. En cuanto a lo que se almacena como los valores en el diccionario, es difícil de decir en función de la información que proporcione, pero los algoritmos de búsqueda suelen utilizar algún tipo de estructura de conjunto para que pueda ejecutar uniones e intersecciones.LINQ le brinda gran parte de esa funcionalidad en cualquier IEnumerable, aunque una clase Set especializada puede aumentar el rendimiento.

Una de estas implementaciones de un conjunto se encuentra en el Wintellect PowerCollections. No estoy seguro de si eso le daría algún beneficio de rendimiento o no sobre LINQ.

En cuanto a guardar en DataSet, no estoy seguro de lo que está imaginando. No estoy al tanto de nada que "automágicamente" escriba en un DataSet. Sospecho que tendrá que escribir esto usted mismo, especialmente porque ha mencionado varias veces que otras opciones de terceros no son lo suficientemente flexibles.

Cuestiones relacionadas