我已经使用 sql 和基于实体值属性的数据库设计实现了树结构查询机制。我想看看基于 XQuery 的方法的相同功能的性能,假设可以使用 XQuery 来完成任务。我的树(XLM 文档)的简化形式如下:
有不同类型的节点,但我在查询中使用的唯一属性是节点的 archetype_node_id 属性。我尝试编写的测试查询旨在选择具有 2 个元素节点的评估节点(在右侧)。查询实现需要所用语言的两个关键功能:支持结构定义的能力(使用布尔运算符),以及定义节点属性约束的能力(在这种情况下为 xml 属性)。
使用 XQuery,我有两个问题 1) 我似乎无法声明对所有感兴趣节点的引用,即我在图中感兴趣的任何节点 2) 我不知道如何返回匹配项,因为这棵树右侧的匹配项将具有一个具有评估的组合,而评估又具有两个元素。
这是我第一次尝试使用 FLWR:
for $composition in doc("composition-visit.xml")//element()
let $evaluation := (
for $evalsneeded in $composition//element()
let $elementat02 :=
(for $el02 in $evalsneeded//element()
where $el02/@archetype_node_id = 'at0002'
and exists($evalsneeded//$el02)
return $el02
),
$elementat03 :=
(for $el03 in $evalsneeded//element()
where $el03/@archetype_node_id = 'at0003'
and exists($evalsneeded//$el03)
return $el03
)
where $evalsneeded/@archetype_node_id = 'openEHR-EHR-EVALUATION.goal.v1'
and
exists ($evalsneeded//$elementat02)
and
exists ($evalsneeded//$elementat03)
return $evalsneeded)
where $composition/@archetype_node_id = 'openEHR-EHR-COMPOSITION.encounter.v1'
and exists($composition//$evaluation)
return $evaluation/@archetype_node_id/string(.)
我的问题是我最终将评估和元素节点推送到子查询,因为如果我将它们作为主要 FLOWR 主体中的全局变量引入,则基于它们的属性值和位置进行过滤不起作用。
在返回结果时我更加一无所知,但我不想为此提出单独的问题。
理想情况下,当我对具有 at0002 和 at0003 代码的元素的评估强制执行 AND 约束时,我应该得到树的右侧,如果我对相同的元素使用 OR 约束,我应该得到整个树。
这对 XQuery 可行吗?它可以作为我在树中寻找的结构是否存在的测试,但我也想访问单个节点。
更新:这是我的第二次尝试。这实际上为我一直在尝试做的事情打开了大门,但我不确定这是否是在 XQuery 中执行此操作的正确方法。我应该问另一个问题来改进这种方法吗?:
<result>
{
for $composition in doc("composition-visit.xml")//element()
where $composition/@archetype_node_id = 'openEHR-EHR-COMPOSITION.encounter.v1'
return <composition>
<name>{$composition/name/value/string(.)}</name>
<evaluation>{for $eval in $composition//element()
let $el1 := (for $el1_in_eval in $eval//element()
where $el1_in_eval/@archetype_node_id = 'at0002'
return $el1_in_eval ),
$el2 := (for $el2_in_eval in $eval//element()
where $el2_in_eval/@archetype_node_id = 'at0003'
return $el2_in_eval )
where $eval/@archetype_node_id = 'openEHR-EHR-EVALUATION.goal.v1'
and
(exists($el1)
and
exists($el2)
)
return <eval>
<name>{$eval/name/value/string(.)}</name>
<element1>{for $element1 in $eval//element()
where $element1/@archetype_node_id = 'at0002'
return $element1}</element1>
<element2>{for $element2 in $eval//element()
where $element2/@archetype_node_id = 'at0003'
return $element2}</element2>
</eval>
}</evaluation>
</composition>
}
</result>
基本上,我使用 let 语句强制执行父/子关系,并使用 return 来获取 let 对应匹配项的值,这反过来可能会在树下做同样的事情。