【问题标题】:Ordering results dynamically in marklogic在marklogic中动态排序结果
【发布时间】:2014-12-03 17:05:55
【问题描述】:

所以,这是我的问题 -
我想根据一组确定排序字段和顺序的变量来排序列表

本质上我需要动态地“排序”。

EG:

    declare function getSearchResults(
        $query as cts:query,
        $sort as xs:string*,
        $direction as xs:string*,    
) as element()*  {

        let $results := 
        cts:search(/*, $query)

        let $sortFields := fn:tokenize($sort, "\|")
        let $dec := $direction = 'desc' or $direction = 'descending'
        let $sorted := sortByFields($results, $sort,$dec)

        return $sorted
};


declare private function sortByFields ($results, $sortFields, $dec)
{
let $asc := fn:not($dec)
for $i in $results

order by

    if ($sortFields[1]='id' and $asc) then $i//ldse:document/@id else (),
    if ($sortFields[1]='id' and $dec) then $i//ldse:document/@id else () descending,

    if ($sortFields[1]='title' and $asc) then $i//title else (),
    if ($sortFields[1]='title' and $dec) then $i//title else () descending

return if (fn:count($sortFields) > 1 ) then (sortByFields($i,$sortFields[2 to fn:count($sortFields)],$dec)) else ($i)
};

此方法不起作用,因为它必须多次排序,并且不会保留每次迭代的排序顺序。

我也试过这个:

let $sortFields := fn:tokenize($sort, "\|")
let $dec := $direction = 'desc' or $direction = 'descending'
let $asc := fn:not($dec)
for $i in $results
    for $j in 1 to fn:count($sortFields)

    order by

        if ($sortFields[$j]='id' and $asc) then $i//ldse:document/@id else (),
        if ($sortFields[$j]='id' and $dec) then $i//ldse:document/@id else () descending,

        if ($sortFields[$j]='title' and $asc) then $i//title else (),
        if ($sortFields[$j]='title' and $dec) then $i//title else () descending

return $i

但这会重复我的数据。 (返回按每个排序字段排序)

由于代码注入,我不想使用 xdmp:eval,有什么办法可以做到这一点吗?

任何帮助或建议将不胜感激。

非常感谢!

【问题讨论】:

    标签: dynamic xquery marklogic


    【解决方案1】:

    需要考虑的几件事。 如果您对 cts:search() 的结果进行排序,则必须先返回所有结果,然后才能对其进行排序。这意味着您无法进行有效的分页。例如。如果您有一百万行并且想要前 100 行......如果您动态订购它,那么您必须获取 100 万行。如果这是一个问题,则需要更复杂的解决方案。

    在实现方面,这是使用函数项的一个很好的例子......但是要使升序/降序工作需要静态分析。或者,它总是可以升序(或降序),但值为正/负。 例如

    for $r in cts:search(...) 
    order by myfunc($r, $criteria)
    return $r
    
    declare function myfunc( $r , $criteria ) as xs:double
    {
      ... logic to order $r in a natural ordering of -inf ... +f..
      return $ordering
    };
    

    但在深入研究之前,我建议先查看 search:search()。

    http://docs.marklogic.com/search:search#opt-sort-order

    其中有一些非常强大的功能,包括能够将复杂的排序定义为 xml 元素。

    最终要有效地进行自定义排序,您可能需要创建范围索引,以便可以在服务器本身而不是您的代码中完成排序。对于小型数据集,这不是什么大问题,但是当您开始搜索数千、数十万或数百万个文档时,您无法在每次搜索时有效地将它们全部拉入内存(或者即使可以,它也会很慢)。不仅所有结果都必须被拉入内存以开始排序,而且 xquery 代码必须针对每个术语进行评估。使用索引,结果集通常可以直接在右边返回,甚至不需要加载文档。

    您还可以使用其他技术,例如将结果加载到地图或数组中、创建自排序树结构、预先创建数据的自定义子集等。

    首先看一下 search:search 库...您甚至可以定义自己的搜索语法供用户输入,所有类型和注入都是安全的,并且多年来得到了很好的优化。

    【讨论】:

    • @StuBob 如果此答案帮助您解决了问题,请接受答案(勾选绿色复选标记)。另外,欢迎来到 SO!
    猜你喜欢
    • 2020-01-15
    • 1970-01-01
    • 2011-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-18
    • 1970-01-01
    • 2023-04-05
    相关资源
    最近更新 更多