使用xquery和FLWOR在BaseX中迭代大型XML文档的最有效方法

时间:2019-06-19 11:09:10

标签: xquery basex flwor

我面临一个有趣的问题,我需要浏览多个大型XML文件(每个文件数百MB),并从每个元素中输出特定数据,并尽快完成。 例子:

Points.xml:

<points>
  <point>
    <identifier>bb25c66c-27d0-447f-aaad-bd8290b332fd</identifier>
    <name>A</name>
  </point>
  <point>
    <identifier>f187cc74-2709-4464-995c-b3bdcae46b39</identifier>
    <name>B</name>
  </point>
</points>

Routes.xml:

<routes>
  <route>
    <pointLink xlink:href="urn:uuid:bb25c66c-27d0-447f-aaad-bd8290b332fd"/>
    <name>1</name>
  </route>
  <route>
    <pointLink xlink:href="urn:uuid:f187cc74-2709-4464-995c-b3bdcae46b39"/>
    <name>2</name>
  </route>
</routes>

在不同的文档中有成千上万的点/路线元素,并且比这要复杂得多,但是对于此示例,此摘录就足够了。

输出必须是这样的:

1 - A
2 - B

我无法修改文档本身,这是我必须要使用的文档,现在的问题是-如何尽可能有效地基于标识符链接元素?我说的是这样做的方式,也许是一种不同的思考方式,而不是实际的代码,因为最终反而会完全不同。

我尝试遍历路线,然后使用FLWOR查找点:

for $route in doc('routes.xml')/routes/route
  return concat(
    $route/name/text(),
    ' - ',
    doc('points.xml')/points/point[./identifier/text() = substring-after($route/pointLink/@xlink:href, 'urn:uuid:')]/name/text()
  )

效果不是很好(花了将近一个小时才能完成)。这种方法也有类似的故事:

for $route in doc('routes.xml')/routes/route,
    $point in doc('points.xml')/points/point[./identifier/text() = substring-after($route/pointLink/@xlink:href, 'urn:uuid:')]
  return concat(
    $route/name/text(),
    ' - ',
    $point/name/text()
  )

最后,我将需要在输出中使用来自点/路径的更多子元素,因此我认为我必须使用for对其进行迭代,然后合并输出,但也许我错了,这就是为什么我在这里问。

有什么我要忽略的东西吗?或者根本没有更快的方法可以做到这一点?

1 个答案:

答案 0 :(得分:1)

正如马丁·霍恩(Martin Honnen)在评论中说的那样,问题的确确实是索引。 简单地创建属性索引(CREATE INDEX属性)有助于将查询时间从〜45分钟减少到不到一秒钟。不可思议。