【问题标题】:Search multiple XML files for string在多个 XML 文件中搜索字符串
【发布时间】:2012-05-17 22:47:00
【问题描述】:

我有一个包含 400k+ XML 文档的文件夹,还有更多,每个文件都以“ID”.xml 命名,每个文件都属于一个特定的用户。在 SQL 服务器数据库中,我将 XML 文件中的“ID”与用户 ID 匹配,这是我将 XML 文档与用户互连的地方。用户可以附加无限数量的 XML 文档(但假设最多 >10k 个文档)

所有 XML 文档都有一些共同的元素,但结构可能会有所不同。

现在,每个用户都需要在属于她的 XML 文档中进行搜索,而到目前为止我所尝试的方法(遍历每个文件并使用流式阅读器读取它)太慢了。我不在乎,如果它读取并匹配整个文件的属性等等,或者只是每个元素中的文本。首先应该返回的是一个包含文件名中 ID 的列表。

如果有的话,这里最快和最聪明的方法是什么?

【问题讨论】:

  • 一次性解析 Xml 文件并使用 Lucene.Net 对其进行索引。

标签: c# asp.net xml .net-3.5


【解决方案1】:

我觉得LINQ-to-XML大概是你想去的方向。

假设您知道所需标签的名称,您将能够搜索这些特定元素并返回值。

var xDoc = XDocument.Load("yourFile.xml");

var result = from dec in xDoc.Descendants()
             where dec.Name == "tagName"
             select dec.Value;

results 将包含名称与“tagName”匹配的任何 XML 标记的值的 IEnumerable

查询也可以这样写:

var result = from dec in xDoc.Decendants("tagName")
             select dec.Value;

或者这个:

var result = xDoc.Descendants("tagName").Select(tag => tag.Value);

输出是一样的,只是根据元素名称过滤的方式不同。

【讨论】:

  • 做了这样的事情,暂时在搜索时间是可以接受的: IEnumerable result = xDoc.Descendants("Root").Where(dec => dec.Value.ToLower ().包含(TextBox1.Text.ToLower()))。选择(dec => dec.Name);
【解决方案2】:

您必须打开每个包含相关数据的文件,如果您不知道哪些文件包含它,则必须打开所有可能匹配的文件。因此,唯一的性能提升将在解析例程中。

在解析 Xml 时,如果需要速度,您可以使用 XmlReader,因为它的性能比其他解析器好得多(大多数在查询之前读取整个 Xml 文件)。对于这种情况,它只转发的事实不应成为限制。

如果解析的时间与磁盘 I/O 一样长,您可以尝试并行解析文件,这样一个线程可以等待读取文件,而另一个线程解析加载的数据。不过,我不认为你可以在 那里取得很大的胜利。

还有什么是“太慢”,什么是可以接受的?许多文件的这种解决方案会随着时间的推移而变慢吗?

【讨论】:

    【解决方案3】:

    使用 LINQ to XML。

    查看this 文章。在 msdn 上。

    XDocument doc = XDocument.Load("C:\file.xml");
    

    别忘了读这么多文件总是很慢,你可以试试写一个多线程的程序……

    【讨论】:

      【解决方案4】:

      如果我理解正确,您不想为特定用户打开每个 xml 文件,因为无论您使用 linq to xml 还是其他方法都太慢了。 您是否考虑过在 xml 文件和关系数据库(标签)(连同 xml ID)中保存一些值。 在这种情况下,您可以先在 DB 中搜索一些值,然后仅选择包含搜索值的 xml 文件?

      例如: ID、标签名称1、标签名称2 xmlDocID,值1,值2

      我的另一个问题是,您为什么选择将 xml 文档存储在文件系统中。如果您使用的是 SQL Server 2005/2008,它对存储、搜索 xml 列(甚至索引 xml 中的某些值)有很好的支持

      【讨论】:

      • Havn 没有考虑到这一点,但我会看看 Linq to XML 的性能是否比我的流式阅读器更好 - 希望它确实如此。评论您的问题:XML 文档每晚从不同的来源分批上传 - 通过 ftp 等,他们可以选择编辑它们一段时间......
      • 好的,如果 linq to xml 仍然执行缓慢,您可以进行某种 xml 后处理(在上传 xml 之后)并将一些感兴趣的值存储在 db..
      • 如果您能确定 XML 中用于搜索的内容,则为这种方法+1。
      【解决方案5】:

      您是否只是在 somewhere 的内容中寻找具有特定字符串的文件?

      警告 - 不是纯 .NET 解决方案。如果这让您感到害怕,请坚持使用其他答案。 :)

      如果您正在这样做,另一种选择是让grep 之类的东西为您完成繁重的工作。使用“-l”参数来说明您只对文件名感兴趣并且您是赢家。 (更多使用示例见this link)

      【讨论】:

      • 如果它只在文本区域而不是在属性、名称等中找到内容,那将是最好的......但我会看看,看看哪个表现最好。即使它让我有点害怕;-)
      【解决方案6】:

      L.B 已经提出了有效的观点。 在这种情况下,Lucene.Net(或任何索引器)是必须的。它会在所有搜索中为您提供稳定(非常快速)的性能。处理大量任意数据是索引器的主要优势之一。

      或者有什么原因,你为什么不使用 Lucene?

      【讨论】:

      • 其实我不知道 Lucene.Net。但是我收到了新的 XML 文件,这不是索引的问题吗?但是从来没有看过索引,但如果有这么多的收获,也许我应该看看?
      • 并非如此 - 您不需要每次都重新索引整个结构。仅在您编写新 XML 文件的子文件夹中启动索引器。但是,如果您需要 - 您可以安排它每天运行 2 次完整的重新索引或其他操作。无论如何,你说 - 索引器做的工作并不比你要做的多。所以你不妨使用索引器
      【解决方案7】:

      Lucene.NET(和 Lucene)支持增量索引。如果您可以每隔一段时间重新打开索引进行阅读,那么您可以整天将文档添加到索引中——您的搜索将与您上次重新打开索引进行搜索时保​​持同步。

      【讨论】:

        猜你喜欢
        • 2011-04-28
        • 1970-01-01
        • 1970-01-01
        • 2011-02-04
        • 1970-01-01
        • 2021-11-04
        • 1970-01-01
        • 2018-01-13
        相关资源
        最近更新 更多