2010-01-21 3 views
6

Je suis en train d'écrire une application interne qui contient plusieurs informations textuelles ainsi qu'un certain nombre de données sur ces textes. Ces éléments de données seront conservés dans une base de données (SQL Server, bien que cela puisse changer) dans l'ordre d'entrée. Je voudrais être en mesure de rechercher les informations les plus pertinentes, les plus pertinentes étant celles qui se trouvent en haut de la page. À l'origine, je me suis penché sur l'utilisation de la recherche en texte intégral de SQL Server, mais ce n'est pas aussi flexible que je l'avais espéré pour mes autres besoins. Il me semble donc que je devrais développer ma propre solution. D'après ce que je comprends ce qui est nécessaire est un inverted index, puis pour le contenu de l'index inversé à restaurer et à modifier en fonction des résultats de l'information supplémentaire détenue (bien que pour l'instant, cela peut être laissé pour une date ultérieure Je veux juste que l'index inversé indexe le texte principal de la table de base de données/chaînes fournies).Rédaction d'un index inversé en C# pour une application de recherche d'information

J'ai eu une chance d'écrire ce code en Java en utilisant un Hashtable avec la clé comme les mots et la valeur comme une liste des occurrences du mot mais en toute honnêteté je suis encore assez nouveau chez C# et ont seulement vraiment utilisé des choses comme DataSets et DataTables lors du traitement des informations. Si demandé, je téléchargerai le code Java dès que j'aurai vidé ce portable de virus.

Si un ensemble d'entrées est donné à partir d'une table ou d'une liste de chaînes, comment créer un index inversé en C# qui sera de préférence sauvegardé dans un DataSet/DataTable? J'ai oublié de mentionner que j'ai déjà essayé Lucene et Nutch, mais j'ai besoin de ma propre solution car modifier Lucene pour répondre à mes besoins prendrait beaucoup plus de temps que d'écrire un index inversé. Je vais gérer beaucoup de méta-données qui auront aussi besoin d'être manipulées une fois l'index inversé de base terminé, donc tout ce dont j'ai besoin pour l'instant est une recherche basique de texte intégral sur une zone utilisant l'index inversé. Enfin, travailler sur un index inversé n'est pas quelque chose que je dois faire tous les jours, donc ce serait génial d'avoir un crack.

+0

Voici un autre index inversé C# basé sur des génériques: http://www.aleandmusic.com/InvertedIndex.aspx –

Répondre

4

Voici un bref aperçu d'une approche que je l'ai utilisé avec succès en C# dans le passé:

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

       } 

      } 
     } 

Notes:

itère GetNextWord() à travers le champ et renvoie le mot suivant et la position . Pour l'implémenter, regardez en utilisant les méthodes de vérification des types de caractères string.IndexOf() et char (IsAlpha etc.).

GetDatabaseTextFieldForID() et GetDatabaseFieldIDS() s'expliquent d'eux-mêmes, implémentent comme requis.

+0

Désolé pour le grand retard dans le retour à cette réponse. Cela a l'air génial! La seule question que j'ai avec ceci est comment on pourrait alors écrire votre dictionnaire dans une base de données. J'ai édité la question avec ce que je veux dire. –

+0

Désolé, je viens de regarder par-dessus le code et j'ai réalisé que je pouvais juste dupliquer les mots s'ils apparaissaient dans plus d'un document. Il devrait être assez facile de l'envoyer à mes classes de gestion de base de données; Une fois que je l'aurai implémenté, j'accepterai cette réponse. –

+0

@Ender, content que ce fut utile. La sérialisation est une option pour enregistrer/charger à partir des bases de données. Alternativement itérer à travers la collection Dictionary Keys et obtenir chaque valeur correspondante serait une autre. – Ash

2

Lucene.net peut être votre meilleur pari. C'est un moteur de recherche plein texte mature utilisant inverted indexes.

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

MISE À JOUR:

J'ai écrit une petite bibliothèque pour l'indexation contre les collections en mémoire à l'aide Lucene.net - il pourrait être utile pour cela. https://github.com/mcintyre321/Linqdex

+0

J'aurais dû expliquer dans ma question que j'avais déjà examiné en utilisant Lucene ou en remplaçant des parties de sa fonctionnalité avec ce que J'ai écris. Malheureusement, Lucene n'est pas assez flexible pour que je puisse changer ce dont j'ai besoin pour répondre aux critères de l'information que j'ai besoin d'avoir, donc je vais devoir écrire moi-même l'index inversé. –

+0

Curieusement, mon expérience avec Lucene.net est que c'est * trop * flexible, ce qui rend les tâches faciles à faire une corvée. De plus, cela ne fonctionne pas correctement avec une confiance moyenne. De plus, la philosophie de rester fidèle à Java signifie que de nombreux idiomes C#/.NET pratiques et performants ne sont pas utilisés. Dommage parce que c'est génial à bien des égards. –

1

Si vous cherchez à faire votre propre, la classe Dictionary<T> sera probablement votre base, comme vos hashtables Java. En ce qui concerne ce qui est stocké en tant que valeurs dans le dictionnaire, il est difficile de dire sur la base des informations que vous fournissez, mais généralement les algorithmes de recherche utilisent un type de structure Set pour pouvoir exécuter des unions et des intersections.LINQ vous donne une grande partie de cette fonctionnalité sur n'importe quel IEnumerable, bien qu'une classe Set spécialisée puisse augmenter les performances.

Une telle implémentation d'un ensemble se trouve dans Wintellect PowerCollections. Je ne suis pas sûr si cela vous donnerait un avantage de performance ou pas sur LINQ.

En ce qui concerne l'enregistrement dans un DataSet, je ne suis pas sûr de ce que vous envisagez. Je ne suis pas au courant de quoi que ce soit qui "automagiquement" écrit dans un DataSet. Je suppose que vous devrez l'écrire vous-même, d'autant plus que vous avez mentionné plusieurs fois que d'autres options tierces n'étaient pas assez flexibles.

Questions connexes