XQuery基于xml结构创建where子句作为一种动态where子句

时间:2016-02-09 18:07:21

标签: xquery marklogic

这是关于XQuery - 我使用MarkLogic作为数据库。

我有以下示例中的数据:

<instrument name="myTest1" id="test1">
   <daten>
      <daily>
         <day date="2016-02-05">
            <screener>
               <column name="i1">
                  <value>1</value>
                  <bg>red</bg>
               </column>
               <column name="i2">
                  <value>1</value>
                  <fg>lime</bg>
               </column>
               <column name="i4">
                  <fg>black</bg>
               </column>
            </screener>
         </day>
      </daily>
   </daten>
</instrument>

我有很多乐器,每一个都在每日元素中有一个条目,而在screener中,可以有manz列,所有列都有不同的名称。一些筛选器包含的列数多于其他筛选器。每列可以包含一个value元素,一个bg元素和一个fg元素。

我想搜索满足特定标准的工具,这些标准关于哪些列具有具有特定值的子项。示例:我想要一个所有乐器的序列,在给定的一天,列i1的值为1,列i2的值为fg

由于我有很多不同的条件,我不想在XQuery where子句中对它们进行硬编码。我做了一些并且它可以工作,但代码有很多重复,很难维护。

我的问题是,是否可以以编程方式在FLOWR语句中构建where子句,这意味着,基于另一个xml结构,它可能如下所示:

<searchpatterns>
  <pattern name="test1">
     <c>
             <name>i1</name>
             <element>value</element>
             <value>1</value>
          </c>
          <c>
             <name>i2</name>
             <element>fg</element>
             <value>red</value>
             <modifier>not</modifier>
          </c>
  </pattern>
</searchpatterns>

会找到那些仪器,其中筛选器具有列i1,其本身具有值1,并且它也必须不具有带有fg为红色的列i2。

当我按照正常方式查询我的日期时,就像这样:

for $res in doc()/instrument
   where $res/daten/daily/day[@date="2016-02-05"]/screener/column[@name="i1"]/value/text()="1"
      and res/daten/daily/day[@date="2016-02-05"]/screener/column[@name="i2"]/fg/text()!="red"

我想基于XML结构生成这种where子句。

我做了一些关于MarkLogic内置cts的研究:搜索功能及其周围的很多东西,但它似乎是用于其他东西(更多用户交互式搜索)

如果你有一个暗示指向我正确的方向,如果我想要的甚至可能,我会非常感激。谢谢!

2 个答案:

答案 0 :(得分:2)

是的,这可以通过编程方式实现。如果要检查元素是否满足序列中每个项目的测试,则会想到every ... satisfies构造。所以在这种情况下可能是:

for $res in doc()/instrument
where every $pattern in $searchpatterns/pattern/c satisfies (
  let $equal := $res/daten/daily/day[@date="2016-02-05"]/screener/column[@name = $pattern/name]/*[name() = $pattern/element] = $pattern/value
  return if ($pattern/modifier = "not") then not($equal) else $equal
)  
return $res

因此将检查每个$pattern。我假设modifier元素应该修改相等的构造。因此,我们首先检查元素是否满足相等条件,然后检查modifier元素是否等于not。当然,应用相同的想法也可以用来实现其他修饰符。

答案 1 :(得分:2)

doc()/ instrument XPath要求每个文档都有一个instrument元素,然后过滤这些文档。

在可能的情况下,MarkLogic通常会更好地对文档建模,以便您可以使用索引来检索尽可能少的文档。通常最好使用cts:search()而不是XPath来生成序列,以便直接使用索引。

在这种情况下,您可以考虑使用name属性的值作为元素而不是通用“列”。然后,您可以生成一个cts:element-query,该查询匹配包含与名称中的值匹配的cts:element-value-query的名称。

希望有帮助,