Marklogic 在XQuery中使用多个Order By参数动态排序

Marklogic 在XQuery中使用多个Order By参数动态排序,marklogic,marklogic-8,Marklogic,Marklogic 8,我想按多个属性对文档进行排序,这些属性在MarkLogic 8中可能是范围索引,也可能不是范围索引 理想情况下,我会有一个XQuery函数,它将接受一系列节点、一系列属性作为字符串进行排序,以及一系列方向作为字符串进行排序 我通过一个xdmp:value调用完成了这一点,请参见下文。然而,这很容易受到注射的影响。是否有人能够使用xdmp:unpath或xdmp:invoke或完全不同的解决方案来帮助解决问题 xquery version "1.0-ml"; declare function l

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

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

我通过一个
xdmp:value
调用完成了这一点,请参见下文。然而,这很容易受到注射的影响。是否有人能够使用
xdmp:unpath
xdmp: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)

如果可以使用and,您会有更大的灵活性,但这似乎不是一个选项,因为您希望传递一系列节点(可能像在您的示例中那样在内存中构造),并且可能没有针对所有排序键的范围索引

请记住,使用
cts:order
进行
cts:search
将提供最佳排序性能

总而言之,这让你几乎没有选择。使用
xdmp:value
可以被视为一种安全风险,但您可以通过严格的输入验证来抵消这种风险。您可以使用
$sortbys作为xs:QName+
,而不是使用
$sortbys作为xs:string*
。您可以使用
$升序作为xs:boolean+
(以及一些代码调整),而不是将
$方向作为xs:string*
。这将使代码注入变得不可能