Marklogic 如何重组文档以优化
在我的示例中,我遇到了一个问题,即使用相同的属性名(123)添加到多个元素 我们清理了查询并评估了建议的解决方案,所有查询都保持相同的数量级(对于全尺寸查询为15秒),对于应用程序来说太慢了 为了完整起见,我在这里重复这些问题: 原件:Marklogic 如何重组文档以优化,marklogic,Marklogic,在我的示例中,我遇到了一个问题,即使用相同的属性名(123)添加到多个元素 我们清理了查询并评估了建议的解决方案,所有查询都保持相同的数量级(对于全尺寸查询为15秒),对于应用程序来说太慢了 为了完整起见,我在这里重复这些问题: 原件: xquery version "1.0-ml"; declare namespace html = "http://www.w3.org/1999/xhtml"; declare namespace p4ns = "http://www.nvsp.n
xquery version "1.0-ml";
declare namespace html = "http://www.w3.org/1999/xhtml";
declare namespace p4ns = "http://www.nvsp.nl/p4";
declare namespace wijkns = "http://www.nvsp.nl/wijk";
let $segment := ("Bruto","Netto")
let $codes := ("9766","9765","2162","2161","2159") (: full query is 4000 codes:)
let $zoeker0 := cts:search(fn:doc(), cts:element-attribute-range-query(xs:QName("p4ns:postcode"), xs:QName("id"), "=", $codes))
(:
let $zoeker1 := cts:search(/p4ns:postcode, cts:element-attribute-range-query(xs:QName("p4ns:postcode"), xs:QName("id"), "=", $codes))
let $zoeker2 := cts:search(/p4ns:postcode, cts:element-attribute-value-query(xs:QName("p4ns:postcode"), xs:QName("id"), $codes))
:)
let $inhoud1 := $zoeker0//p4ns:segment[@name=$segment]
(:
let $inhoud2 := $zoeker1//p4ns:segment[@name=$segment]/text()
let $r1 := cts:search(/p4ns:postcode, cts:element-attribute-range-query(xs:QName("p4ns:segment"), xs:QName("name"), "=", $segment))
:)
return $inhoud1
接受的答复:
declare namespace p4ns="http://www.nvsp.nl/p4" ;
(: These might be external parameters. :)
let $segment := ("Bruto","Netto")
let $ids := ("9766","9765")
return collection()/p4ns:postcode/p4ns:category/p4ns:variable/p4ns:segment[
@name = $segment]/string()
这两个查询在大型文档中查找段名称属性的成本仍然很高
公认的答案是没有真正好的解决方案,只有重新组织文档
下一个挑战是如何解决
我的思路是:
- 重建文档
- 将文档拆分为两个(或多个)部分
- 使用片段和片段根
- 在同一文档中使用单独的命名空间来拆分内容李>
因此,我的问题是:如何重新构造原始文档,使我的查询在几秒钟内响应。看起来Mike在上一个问题中没有提到路径索引选项。您可以在
/postcode/category[name=“Oplage”]/variable[name=“Oplage”]/segment[name=“Bruto”]上创建索引
具体地说,就是将其用作路径模式。这将有助于尽可能准确地定位相关片段
但是,我不确定您期望的最终结果是什么。您想要一个Bruto段值列表,还是要查找包含匹配段的邮政编码?这在很大程度上取决于您想要的结果。从头到尾考虑这个问题可能很有用
HTH!我不喜欢使用子片段。编写一个意外地将所有片段加载到内存中的查询太容易了。这个用例可能是一个例外,片段可能是最好的方法,但我会把它作为最后的手段。我的经验是,它一开始似乎工作得很好,但随后会导致越来越多的问题问题就在你继续 在上一个问题中,我提到了其他可能性。我将在这里回顾它们。主要技巧是记住MarkLogic是一个面向文档的数据库。因此文档URI是主键,文档的行为更像行而不是表。构造文档和URI,以便最常见的查询能够利用这些字符特性 在MarkLogic中,文档URI是主键,按主键进行查找只是
doc($URI)
。这是查询数据库的一种非常有效的方法。要知道这一点,您应该对内容进行结构化,以便最常见的查找就是doc($URI)
。您提到了一种类似于Oplages/Oplage/Bruto
的结构。我不确定这到底是什么意思,但如果您将其排列为文档URI而不是XML结构,会怎么样?类似于/Oplages/{code}/{segment}
?每个文档都非常小,只有一个片段的数据
如果您有不经常使用的元数据,请将其放在一个特殊的文档中,如/oplages/{code}/metadata.xml
。或者如果每次都使用它,请将其复制到每个片段文档中。您比我更了解您的内容,但单个文档的xml可能如下所示:
<segment xmlns="http://www.nvsp.nl/p4"
postcode="9728"
category="Oplages"
variable="Oplage"
name="Bruto"
updated="2014-08-12+02:00">
1234
</segment>
1234
使用存储在/oplages/9728/Bruto
的XML,只需调用doc('/oplages/9728/Bruto')
即可获得值。您还可以使用一系列URI调用fn:doc
。您可能会看到,在文档大小和数据结构方面存在权衡
我提到的另一种可能性是使用范围索引和或来查询数据。这种方法直接从值索引中提取数据,而不是检查XML树。但是,对于定义良好的小文档,这种方法更容易。对于像原始示例一样的XML,每个文档包含许多值,您需要定位-感知范围索引和仔细编写的位置范围查询。我测试了Mike和Geert的建议,您可以通过以下方式实现您想要的(我相信这是为了获得邮政编码的bruto和Netto值): 创建两个路径范围索引,一个用于Bruto,一个用于Netto: /p4:邮政编码/p4:类别/p4:变量/p4:段[@name='Bruto'] /p4:邮政编码/p4:类别/p4:变量/p4:段[@name='Netto'] 不要忘记为p4注册名称空间 如果需要将这些段变为变量,则此操作将失败。 然后使用下面的代码,您可以从索引中获得bruto和netto的值
declare namespace p4 = "http://www.nvsp.nl/p4";
let $segment := ("Bruto","Netto")
let $ids := ("9729","9728")
for $id in $ids
return ($id,
cts:value-co-occurrences(
cts:path-reference("/p4:postcode/p4:category/p4:variable/p4:segment[@name='Bruto']"),
cts:path-reference("/p4:postcode/p4:category/p4:variable/p4:segment[@name='Netto']"),(),
cts:element-attribute-value-query(xs:QName("p4:postcode"),xs:QName("id"),$id)))
这将返回一系列具有bruto和netto值的ID,如:
9729 (: id :)
<cts:co-occurrence xmlns:cts="http://marklogic.com/cts" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<cts:value xsi:type="xs:int">4321</cts:value> (: bruto value :)
<cts:value xsi:type="xs:int">2000</cts:value> (: netto value :)
</cts:co-occurrence>
这将返回邮政编码加上给定的段值:
Bruto (: segment name :)
<cts:co-occurrence xmlns:cts="http://marklogic.com/cts" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<cts:value xsi:type="xs:int">9728</cts:value> (: postcode :)
<cts:value xsi:type="xs:int">1234</cts:value> (: segment value :)
</cts:co-occurrence>
Bruto(:段名称:)
9728(:邮政编码:)
1234(:段值:)
是的,我提到了范围索引,但没有建议将段名称硬编码到路径范围索引中。将其与cts:values
一起使用可能会很好,只要有少量段名称需要优化:例如,可能只是Bruto
和Netto
。但也可能有一个开放的段名称,每个段都需要自己的路径范围索引。
Bruto (: segment name :)
<cts:co-occurrence xmlns:cts="http://marklogic.com/cts" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<cts:value xsi:type="xs:int">9728</cts:value> (: postcode :)
<cts:value xsi:type="xs:int">1234</cts:value> (: segment value :)
</cts:co-occurrence>