2014-12-02 3 views
2

그래서, 여기 내 질문입니다 "동적으로.주문 결과는

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을 사용하지 않는 것이 좋을 것입니다.

도움이나 제안 사항을 보내 주시면 감사하겠습니다.

감사합니다.

답변

5

몇 가지 고려해야 할 사항. cts : search()의 결과를 주문하는 경우 주문하기 전에 모든 결과가 반환되어야합니다. 이는 효율적인 페이지 매김을 수행 할 수 없다는 것을 의미합니다. 예 : 백만 열이 있고 상위 100 개가 필요한 경우 ... 동적으로 주문하면 1 백만 행을 가져와야합니다. 이것이 문제라면보다 복잡한 해결책이 필요합니다.

구현 방식은 기능 항목을 사용하는 좋은 경우이지만 오름차순/내림차순 작업을 수행하려면 정적 분석이 필요합니다. 또는 항상 오름차순 (또는 내림차순) 일 수 있지만 값은 양수/음수입니다. 예 :

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 :를 검색하는 것이 좋습니다.

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

XML 요소로 복잡한 순서를 정의 할 수있는 포함이에서 매우 전원 기능이있다.

궁극적으로 맞춤 주문을 효율적으로 수행하려면 코드 대신 서버 자체에서 순서를 지정할 수 있도록 범위 색인을 만들어야합니다. 소규모 데이터 세트의 경우 큰 문제는 아니지만 수천, 수천 또는 수백만 개의 문서를 검색 할 때 모든 검색에서 메모리에 모든 것을 가져올 수 없습니다 (또는 느릴 수도 있음). 정렬을 시작하기 위해 결과를 모두 메모리로 가져와야 할뿐만 아니라 xquery 코드는 모든 용어에 대해 평가되어야합니다. 인덱스를 사용하면 문서를로드하지 않고도 결과 세트를 오른쪽으로 직접 반환 할 수 있습니다.

당신이

검색 한 번 봐 데이터 등의 사용자 지정 하위 집합을 만들어 사전, 같은 트리 구조를 정렬 자체를 작성,지도 나 배열로 결과를로드로 사용할 수있는 다른 방법이 있습니다 : 검색 라이브러리를 먼저 ... 사용자가 입력 할 수있는 검색 구문을 정의 할 수도 있습니다. 모든 유형과 주사는 안전하며 매우 잘 최적화되어 있습니다.

+0

정말 고마워요! – StuBob

+1

@StuBob이 답변으로 문제를 해결하는 데 도움이 되었다면 답을 수락하십시오 (녹색 체크 표시가 나타남). 또한 SO에 오신 것을 환영합니다! – dirkk