【问题标题】:CTS and xPath both necessary?CTS 和 xPath 都需要吗?
【发布时间】:2016-03-23 16:49:20
【问题描述】:

我有以下 CTS 搜索查询:

cts:search(/parent, 
    cts:and-query((
        cts:element-attribute-value-query(xs:QName('parent'), xs:QName('attr'), 'value'),
        cts:element-attribute-value-query(xs:QName('child'), xs:QName('attr-1'), 'value-2'),
        cts:element-attribute-value-query(xs:QName('child'), xs:QName('attr-2'), 'value-3')
    ))
)/child[@attr-1 eq 'value-2' and @attr-2 eq "value-3"]

(: Returns /parent/child elements matching criteria :)

我有一些关于父母的限定词,以及关于孩子的限定词。我想要的最终结果只是孩子们。为了做到这一点,正如你从上面看到的,我必须:

  • 搜索符合父条件 + 子条件的文档
  • 获取该文档后,按与上述相同的条件逻辑过滤掉子项

这行得通,但是我在 cts:query 中必须有与我在 xPath 上为孩子们做的相同的逻辑,这似乎真的很愚蠢。逻辑被不必要地重复。

有没有一种方法可以让我在 cts:query 中完成所有这些操作,而不必像上面的示例那样使用额外的 xPath 表达式?


这和我想要的差不多,但是对cmets中指定的问题不起作用:

cts:search(/parent/child, 
    cts:and-query((
        cts:element-attribute-value-query(xs:QName('parent'), xs:QName('attr'), 'value'), (: The problem is this line... I can't filter by the parent, as it is above the scope of my first parameter (/parent/rule) :)
        cts:element-attribute-value-query(xs:QName('child'), xs:QName('attr-1'), 'value-2'),
        cts:element-attribute-value-query(xs:QName('child'), xs:QName('attr-2'), 'value-3')
    ))
)

【问题讨论】:

    标签: xpath xquery marklogic


    【解决方案1】:

    您仍然可以查询父级,即使您的搜索对象是子级:

    cts:search(/parent/child, 
        cts:and-query((
            cts:element-attribute-value-query(xs:QName('parent'), xs:QName('attr'), 'value'),
            cts:element-attribute-value-query(xs:QName('child'), xs:QName('attr-1'), 'value-2'),
            cts:element-attribute-value-query(xs:QName('child'), xs:QName('attr-2'), 'value-3')
        ))
    )
    

    这将作为过滤搜索运行,但由于您还是手动进行过滤,因此性能应该大致相同。

    更新:

    我对此进行了测试,上面的断言是错误的。我认为这是正确的,但显然cts:search 过滤将过滤与可搜索表达式不完全匹配的结果。父级将超出可搜索表达式的范围。

    理想情况下,您可以在 child 元素上拆分文档,但至少可以像这样删除重叠的查询和 XPath:

    cts:search(/parent/child, 
        cts:and-query((
            cts:element-attribute-value-query(xs:QName('child'), xs:QName('attr-1'), 'value-2'),
            cts:element-attribute-value-query(xs:QName('child'), xs:QName('attr-2'), 'value-3')
        ))
    )[parent::parent/@attr = 'value']
    

    【讨论】:

    • 这对我不起作用。当我将/parent 作为可搜索表达式时,我会从 cts:search 中获取父级。当我输入/parent/child 作为可搜索表达式时,我什么也得不到。 cts:query 本身永远不会改变,我所改变的只是可搜索的表达式。当我拥有/parent/child 时,它不起作用。我的假设是父元素上的第一个元素属性值查询会抛出所有问题,因为它不低于可搜索表达式(?)
    • 感谢您的更新。您还可以轻松地反转逻辑,并从 cts:search 中获取父级,然后使用 xPath 过滤子级。在我的情况下,您过滤孩子的地方实际上会更快,因为它比父母更具体。我仍然希望(根据问题)在 cts 中解决所有这些问题:搜索纯粹的风格原因,但也许这是不可能的。过滤 cts:search 的计算成本是否与通过 xPath 表达式过滤的计算成本相同?
    • @CtheGood 在计算上,让 cts:search 尽可能多地完成繁重的工作是最好的策略。它可以返回的所有结果 unfiltered 将仅使用索引来解决,因此它们会非常快。如果您必须通过 cts:search 或手动通过 XPath 使用过滤,则数据库必须 1)选择比其他方式更多的文档,以及 2)将它们加载到内存中以执行过滤。没有关于如何最大化前者和最小化后者的一般规则 - 它仅取决于您的文档,因此您可以做的就是测试不同的方法。
    【解决方案2】:

    wst 给了你答案。然而,这一切都源于需要过滤。在 MarkLogic 中,想法是一个文档应该反映一个“记录”。是否可以重构您的文档以避免一开始就需要过滤?

    【讨论】:

    • 不,不是。我的文档已经很简单了,每个文档的根元素只有 1 个深子元素(即 )。父母有属性,所有的孩子也一样。我只想获得已经目标父母的几个目标孩子。我总是不得不用双重逻辑来做 - cts:在父级上搜索,然后使用 xPath 通过相同的逻辑进行过滤。但是,我想巩固一下。
    • @CtheGood 使用关系类比详细说明 David 的建议,在 MarkLogic 中,最好将文档视为行,而不是表。为了获得理想的查询性能,您需要在需要查询的数据和单个文档之间建立一对一的关系。在您的情况下,我可能会制作 一个文档(或使用片段根......但要小心)并将任何对从父文档查询重要的数据传播(复制)到子文档。这种类型的“非规范化”在 ML 中非常常见。
    • 当然——这是平衡。不完全是一门艺术 - 但一些个人选择开始发挥作用。您还必须考虑到您不一定需要 MarkLogic 中的小片段,因此如果子文档“很小”(请参阅​​文档以获取指导),那么将它们打包到一定大小并应用过滤是一个可行的选择。例如,即使是 ML 中的三元组(3 个元素和一个父元素)也会在片段中存储大约 100 个,而不是在导入时单独存储。
    猜你喜欢
    • 2014-10-07
    • 1970-01-01
    • 1970-01-01
    • 2019-11-13
    • 2011-07-10
    • 2017-07-13
    • 2012-11-13
    • 1970-01-01
    • 2013-12-23
    相关资源
    最近更新 更多