tree - XQuery可以支持树结构查询吗?

标签 tree xquery openehr

我已经使用 sql 和基于实体值属性的数据库设计实现了树结构查询机制。 我想通过基于 XQuery 的方法查看相同功能的性能,假设可以使用 XQuery 完成任务。 我的树(XLM文档)的简化形式如下: enter image description here

有不同类型的节点,但我在查询中使用的唯一属性是节点的 archetype_node_id 属性。我尝试编写的测试查询旨在选择具有 2 个元素节点的评估节点(在右侧)。查询实现需要所用语言的两个关键功能:支持结构定义的能力(使用 bool 运算符),以及为节点属性(在本例中为 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 的相应匹配项的值,这反过来可能会在树下执行相同的操作。

最佳答案

看起来您的用例正在查询“原型(prototype)”openEHR 数据。

欢迎查看开源 https://github.com/LiU-IMT/EEE将 xQuery 用于类似于您的用例的请求,但数据建模有点不同。

它用于例如在论文中http://www.ep.liu.se/ecp/070/009/ecp1270009.pdf您可以在其中找到一个查询示例,该示例返回在 2006 年 1 月 1 日至 2006 年 5 月 1 日期间具有指示肿瘤病变的组织学检查结果的所有记录 ID。

在AQL(Archetype Query Language)中表示为...

SELECT e/ehr_id/value as ehr_id
FROM Ehr e
CONTAINS VERSION v
CONTAINS COMPOSITION c [openEHR-EHR-COMPOSITION.histologic_exam.v1]
CONTAINS OBSERVATION obs [openEHR-EHR-   OBSERVATION.histological_exam_result.v1]
WHERE (EXISTS obs/data[at0001]/events[at0002]/data[at0003]/items[at0085]/items[at0033]/items[at0034] 
OR
EXISTS obs/data[at0001]/events[at0002]/data[at0003]/items[at0085]/items[at0033]/items[at0035])
AND c/context/start_time/value >= '2006-01-01T00:00:00,000+01:00'
AND c/context/start_time/value < '2006-05-01T00:00:00,000+01:00'`

...当自动解析并转换为 XQuery 时,它看起来像这样:

declare namespace v1 = "http://schemas.openehr.org/v1";
declare default element namespace "http://schemas.openehr.org/v1";
declare namespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
declare namespace eee = "http://www.imt.liu.se/mi/ehr/2010/EEE-v1.xsd";
declare namespace res = "http://www.imt.liu.se/mi/ehr/2010/xml-result-v1#";
<res:xml-results>
<res:head><res:variable name="ehr_id"/></res:head>
<res:results>
 {let $ehrRoot := //eee:EHR
  for $e in $ehrRoot
  for $v in $e/eee:versioned_objects/eee:versions
  for $c in $v//*[@xsi:type='v1:COMPOSITION' and @archetype_node_id="openEHR-EHR-COMPOSITION.histologic_exam.v1"]
  for $obs in $c//*[@xsi:type='v1:OBSERVATION' and @archetype_node_id= "openEHR-EHR-OBSERVATION.histological_exam_result.v1"]
  where
   (
    exists($obs/data[@archetype_node_id = 'at0001']/events[@archetype_node_id = 'at0002']/data[@archetype_node_id='at0003']/items[@archetype_node_id = 'at0085']/items[@archetype_node_id = 'at0033']/items[@archetype_node_id = 'at0034'])
   or
    exists($obs/data[@archetype_node_id = 'at0001']/events[@archetype_node_ id = 'at0002']/data[@archetype_node_id = 'at0003']/items[@archetype_node_id = 'at0085']/items[@archetype_node_id = 'at0033']/items[@archetype_node_id = 'at0035'])
   )
   and
    $c/context/start_time/value >= '2006-01-01T00:00:00,000+01:00' 
   and 
    $c/context/start_time/value < '2006-05-01T00:00:00,000+01:00'
return
<res:result><res:binding name="ehr_id">{$e/eee:ehr_id/value}</res:binding></res:result>}
</res:results>
</res:xml-results>

此模式也值得在您的用例中尝试。有关解决方案和上下文的更多详细信息,请参阅论文 http://www.biomedcentral.com/1472-6947/13/57

关于tree - XQuery可以支持树结构查询吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14016143/

相关文章:

CSS - 列表树背景问题

java - 这些类声明与 Comparable 有什么区别?

php - 从类似于树的 mysql 结果集创建 Json

ruby-on-rails - Rails 多表继承、多态关联还是单表继承?

c++ - 二叉树只添加到根

java - 在 java、OSB、XQuery 中从 XML 获取不同的值

没有 FLWOR 的 xquery 括号

xml - XQuery 中基于变量的动态排序(排序依据)

javascript - Grails 2.4.4 绑定(bind) JSON 嵌套对象