在XQuery中按多个顺序依次动态排序

时间:2017-01-30 23:16:10

标签: marklogic marklogic-8

我想按MarkLogic 8中的多个属性对文档进行排序,这些属性可能是也可能不是范围索引。

理想情况下,我会有一个XQuery函数,它接受一系列节点,一系列属性作为字符串进行排序,以及一系列按字符串排序的方向。

我通过xdmp:value电话完成了此操作,请参见下文。然而,这很容易注射。是否有人能够使用xdmp:unpathxdmp:invoke或完全不同的解决方案来帮助解决方案?

xquery version "1.0-ml";

declare function local:sort-dynamically(
  $nodes as node()*,
  $sortbys as xs:string*,
  $directions as xs:string*
  ) as node()*
{
  (: build the components for the order by string
    model: order by node//property direction
  :)
  let $order-bys := 
    for $i in 1 to count($sortbys)
    return
      "$node//" || $sortbys[$i] || " " || $directions[$i]

  (: join the order bys, separated by comma + space :)
  let $order-bys-string := fn:string-join($order-bys, ", ") || " "

  (: create the eval string
    model: for node in nodes
            order by
              node//property1 direction1, node//property2 direction2
            return
              node
  :)
  let $eval-string :=
      fn:concat(
        "for $node in $nodes ",
        "order by ",
          $order-bys-string,
        "return $node"
      )

  (: evaluate the sort :)
  return
    xdmp:value(
      $eval-string
    )
};

let $nodes := (
  xdmp:unquote('{"col1": "1", "col2": "a"}'),
  xdmp:unquote('{"col1": "1", "col2": "a"}'),
  xdmp:unquote('{"col1": "1", "col2": "b"}'),
  xdmp:unquote('{"col1": "2", "col2": "a"}')
  )
let $sortbys := ("col1", "col2")
let $directions := ("ascending", "descending")

return
  local:sort-dynamically($nodes, $sortbys, $directions)

1 个答案:

答案 0 :(得分:2)

如果你可以使用cts:searchcts:index-order,你会有更大的灵活性,但这似乎没有选择,因为你想传递一系列节点(可能在你的例子中构建在内存中),并且可能没有所有排序键的范围索引。

请注意,虽然cts:search cts:order xdmp:value可以提供最佳排序效果。

总而言之,这给你留下了很少的选择。使用$sortbys as xs:string*可能会被视为安全风险,但您可以通过严格的输入验证来抵消这种风险。您可以使用$sortbys as xs:QName+,而不是使用$directions as xs:string*。而不是$ascending as xs:boolean+,您可以使用<svg version="1.1" id="loader-1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="40px" height="40px" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve"> ... <script type="text/javascript"> window.addEventListener('load',function(){ alert('Hi') }) </script> </svg> (以及一些代码调整)。这会使代码注入不可能..

HTH!