【问题标题】:Writing an Inverted Index in C# for an information retrieval application用 C# 为信息检索应用程序编写倒排索引
【发布时间】:2011-01-07 18:48:52
【问题描述】:

我正在编写一个内部应用程序,其中包含多条文本信息以及有关这些文本的多条数据。这些数据片段将按输入顺序保存在数据库(SQL Server,尽管这可能会改变)中。

我希望能够搜索这些信息中最相关的信息,其中最相关的信息位于顶部。我最初考虑使用 SQL Server 全文搜索,但它不像我希望的那样灵活满足我的其他需求,所以我似乎需要为此开发自己的解决方案。

据我了解,需要的是inverted index,然后根据所持有的附加信息的结果来恢复和修改所述倒排索引的内容(尽管现在可以将其留到以后的日期因为我只希望倒排索引从提供的数据库表/字符串中索引主要文本)。

我在 Java 中使用 Hashtable 编写这段代码,其中键作为单词,值作为单词出现的列表,但老实说,我还是 C# 的新手,并且有仅在处理信息时才真正使用 DataSets 和 DataTables 之类的东西。如果需要,我会在清除这台笔记本电脑的病毒后尽快上传 Java 代码。

如果给定一个表或字符串列表中的一组条目,如何在 C# 中创建一个倒排索引,该索引最好保存到 DataSet/DataTable 中?

编辑:我忘了提到我已经尝试过 Lucene 和 Nutch,但需要我自己的解决方案,因为修改 Lucene 以满足我的需要比编写倒排索引需要更长的时间。我将处理大量元数据,一旦基本倒排索引完成,这些元数据也需要处理,所以我现在需要的是使用倒排索引在一个区域上进行基本的全文搜索。最后,倒排索引不是我每天都要做的事情,所以如果能尝试一下就好了。

【问题讨论】:

标签: c# search data-structures full-text-search


【解决方案1】:

以下是我过去在 C# 中成功使用的一种方法的粗略概述:

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

                }

            }
        }

注意事项:

GetNextWord() 遍历该字段并返回下一个单词和位置。要实现它,请查看使用 string.IndexOf() 和 char 字符类型检查方法(IsAlpha 等)。

GetDatabaseTextFieldForID() 和 GetDatabaseFieldIDS() 不言自明,按需实现。

【讨论】:

  • 很抱歉在回复此答案时出现巨大延迟。这看起来很棒!我对此的一个问题是如何将您的字典写回数据库。我已经按照我的意思编辑了这个问题。
  • 抱歉,我刚刚查看了代码并意识到如果单词出现在多个文档中,我可以复制它们。将它发送到我的数据库处理类应该很容易;一旦我得到这个实施,我会接受这个答案。
  • @Ender,很高兴它有帮助。序列化是从数据库保存/加载的一种选择。或者,遍历 Dictionary Keys 集合并获取每个对应的值将是另一个。
  • 我已经成功地通过使用 LINQ 来获取每个值来实现它,所以我接受了这个答案。只是出于兴趣,您将如何实现 GetNextWord() 方法,因为我已将整个字段拆分为单独的单词并迭代直到它们全部消失。
【解决方案2】:

Lucene.net 可能是您最好的选择。它是一个成熟的全文搜索引擎,使用inverted indexes

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

更新:

我编写了一个小库,用于使用 Lucene.net 对内存中的集合进行索引 - 它可能对此有用。 https://github.com/mcintyre321/Linqdex

【讨论】:

  • 我应该在我的问题中解释说我已经研究过使用 Lucene 或用我编写的内容替换它的部分功能。遗憾的是 Lucene 不够灵活,我无法更改我需要的内容以满足我需要保存的信息的标准,因此我需要自己编写倒排索引。
【解决方案3】:

如果您想自己动手,Dictionary&lt;T&gt; 类很可能会成为您的基础,就像您的 Java 哈希表一样。就字典中存储的值而言,很难根据您提供的信息来判断,但通常搜索算法使用某种类型的 Set 结构,因此您可以运行联合和交集。 LINQ 在任何 IEnumerable 上为您提供了大部分功能,尽管专门的 Set 类可能会提高性能。

Set 的一个这样的实现是在Wintellect PowerCollections 中。我不确定这是否会给您带来任何性能优势,或者不会超过 LINQ。

至于保存到DataSet,我不确定您的设想。我不知道任何“自动”写入DataSet 的内容。我怀疑您将不得不自己编写此内容,尤其是因为您多次提到其他第三方选项不够灵活。

【讨论】:

    猜你喜欢
    • 2014-11-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多