2017-01-30 3 views
1

Я хотел бы сортировать документы по нескольким свойствам, которые могут или не могут быть диапазоном индексированных в MarkLogic 8.Динамически Сортировать с множественными Сортировать по Аргументам в XQuery

В идеале я хотел бы иметь функцию 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) 

ответ

2

Вы бы иметь больше гибкости, если вы могли бы использовать cts:search и cts:index-order, но это кажется не вариант, как вы хотите передать в последовательности узлов (потенциально построенных в памяти, как в вашем примере), и может не иметь индексы диапазона для всех ключей сортировки.

Имейте ввиду, что cts:search с cts:order даст лучшую производительность сортировки.

В целом, это оставляет вам мало возможностей. Использование xdmp:value можно рассматривать как угрозу безопасности, но вы можете противодействовать этому при строгой проверке ввода. Вместо использования $sortbys as xs:string* вы можете использовать $sortbys as xs:QName+. И вместо $directions as xs:string* вы можете использовать $ascending as xs:boolean+ (вместе с некоторыми корректировками кода). Это сделало бы инъекцию кода невозможной.

HTH!

Смежные вопросы