' xdmp:eval and building the xquery order string through a function.'


xdmp:eval()  should be avoided if at all possible, especially with dynamically 
created string content its

incurs a significant overhead and opens the possibility of XQuery injection.

eval and invoke are intended for when you need contextual changes otherwise 
impossible (such as a new transaction,

running in a different module or DB etc).

*almost* anything else you can do with XQuery 3.x named and anonymous functions 
much easier, safer  and faster.



First consider that use of indexes and cts:search or search:search may 
implement what you want much better then XPath

and may not require an order-by depending on the range indexes.

search:search directly allows runtime sort order :



https://docs.marklogic.com/search:search



See:
<sort-order>
Set the default sort order. The first such element is the primary sort order, 
the second secondary sort order, and so on. The default is to sort by score, 
descending. Note that the default scoring algorithm can be set just like any 
other option with the option named search-option. If you are sorting by an 
element or an attribute, you must specify a type attribute with a value 
corresponding to the range index type of that element or attribute (for 
example, xs:string, xs:dateTime, and so on). If the corresponding range index 
is of type xs:string, then you can optionally specify a collation attribute 
(otherwise the collation of the query is used). To change the sorting 
direction, specify an optional directionattribute with a value of decending 
(the default) or ascending.
The sort-order element must have one of a single element child, a single score 
child, a single field child, or a single json-property child. If there is a 
score child, it specifies to sort by the score of the search result. If there 
is an element child it can optionally have an attribute sibling (to specify an 
attribute of the preceding element). Both the element and attribute elements 
must have ns and name attributes to specify the namespace and local-name of the 
specified element and attribute. Additionally, the sort-order element can have 
0 or more annotation elements (to add comments, for example). You should not 
apply sort-order to a field backed by a field range index with more than one 
included element.
For example, the following specifies a primary sort order using the element 
value for my-element (which needs a string range index with the specified 
collation), and a secondary sort order of score ascending:
<sort-order type="xs:string"
    collation="http://marklogic.com/collation/";
    direction="ascending">
  <element ns="my-namespace" name="my-element"/>
  <annotation>some user comment can go here</annotation>
</sort-order>
<sort-order direction="ascending">
  <score/>
</sort-order>

The search library is very powerful and adopts 'best practice' over a large 
range of features.









If that doesnt work ...



Are your element names from an infinate unknown set (i.e literally any name 
might be used),

or are they from a fixed set (>1) ?

If its a compile time fixed set you can do some optimizations, including making 
range indexes over the

sort fields ...

--- Here are some examples to play with - not your exact structure, I used this 
code to generate 10000 docs with 10 items of E{1...10} each



xdmp:document-delete(cts:uris());



declare variable $qn := ( 1 to 10 ) ! fn:QName( "" , "E" || . );



for $i in 1 to 10000

return xdmp:document-insert( "/test."||$i||".xml" ,



   <doc>{

     for $item in 1 to 10

     return

       <item> {

          for $q in $qn return

           element {  $q    } { xdmp:random(100) } ,

         <value>The items value is: {$item}</value>

        }</item>

        }

       </doc> )







------------   And here's a test program showing some different ways of doing 
things ---

Adding a range index to all the E* items helped a lot in some of the tests but 
not others.

This case I used a trick to simplify the ascending/descending case - the values 
are numeric so multiple by 1/-1

For text you may need to replicate the functions for ascending or descending or 
reverse the results afterwards.

In all these cases - performance will be improved dramatically if you can 
*first* filter the set of possible documents

before doing the sort -







declare variable $sort-name external := "E5" ;

declare variable $sort-elem external := element { xs:QName($sort-name)  } {}  ;

declare variable $sort-order external := 1;





(: Dynamic name lookup :)

declare variable $compare1:=

  function( $result as element() ) as xs:double  {

     $result/*[fn:local-name() eq $sort-name]/fn:data() * $sort-order

};



(: faster static lookup  :)



declare variable $compare2:=

  function( $result as element() ) as xs:double  {



    typeswitch( $sort-elem )

    case element( E1 ) return $result/E1

    case element( E2 ) return $result/E2

    case element( E3 ) return $result/E3

    case element( E4 ) return $result/E4

    case element( E5 ) return $result/E5

    case element( E6 ) return $result/E6

    case element( E7 ) return $result/E7

    case element( E8 ) return $result/E8

    case element( E9 ) return $result/E9

    case element( E10 ) return $result/E10

    default return fn:error( () , "Unknown element : " , $sort-elem )

    / fn:data() * $sort-order





};



declare function local:test(  ) {



for $result in (/doc/*)

  order by $result/E5 ascending

return $result/value

};



declare function local:test1( ) {

for $result in (/doc/*)

  order by $compare1( $result )

return $result/value

};





declare function local:test2( ) {

for $result in (/doc/*)

  order by $compare2( $result )

return $result/value

};





declare function local:test3()

{



for $result in (/doc/*)

order by



typeswitch( $sort-elem )

    case element( E1 ) return $result/E1

    case element( E2 ) return $result/E2

    case element( E3 ) return $result/E3

    case element( E4 ) return $result/E4

    case element( E5 ) return $result/E5

    case element( E6 ) return $result/E6

    case element( E7 ) return $result/E7

    case element( E8 ) return $result/E8

    case element( E9 ) return $result/E9

    case element( E10 ) return $result/E10

    default return fn:error( () , "Unknown element : " , $sort-elem )

    / fn:data() * $sort-order

  return $result/value





};



-----------------------------------------------------------------------------

David Lee

Lead Engineer

MarkLogic Corporation

d...@marklogic.com

Phone: +1 812-482-5224

Cell:  +1 812-630-7622

www.marklogic.com



-----Original Message-----
From: general-boun...@developer.marklogic.com 
[mailto:general-boun...@developer.marklogic.com] On Behalf Of Vanheeswijck David
Sent: Tuesday, May 05, 2015 5:03 AM
To: general@developer.marklogic.com
Subject: Re: [MarkLogic Dev General] Dynamic order by (message 4)



I've solved this by using xdmp:eval and building the xquery order string 
through a function.



Do you need an example ?





------------------------------



Message: 4

Date: Tue, 5 May 2015 04:04:45 +0000

From: "Kapoor, Pragya" <pkapo...@innodata.com<mailto:pkapo...@innodata.com>>

Subject: Re: [MarkLogic Dev General] Dynamic order by

To: MarkLogic Developer Discussion 
<general@developer.marklogic.com<mailto:general@developer.marklogic.com>>

Message-ID: 
<1430798685003.81...@innodata.com<mailto:1430798685003.81...@innodata.com>>

Content-Type: text/plain; charset="utf-8"



Could someone help on this?



________________________________

From: Kapoor, Pragya

Sent: Monday, May 4, 2015 5:03 PM

To: MarkLogic Developer Discussion

Subject: Re: [MarkLogic Dev General] Dynamic order by





Thanks Asit.



But I have different requirement.



In your code :



return if($sorting/sorting/sort) then

for $each in $results//results/result

order by $each/AgreementType descending , $each/CollectionNo ascending return 
$each (: modify as per your business requirement :) else $results



In the order by clause you are using $each/AgreementType, but as mentioned in 
the mail the element AgreementType is not static. This value is dynamic 
moreover sort direction(asc/desc) is also dynamic.



?Thanks

Pragya





________________________________

From: 
general-boun...@developer.marklogic.com<mailto:general-boun...@developer.marklogic.com>
 
<general-boun...@developer.marklogic.com<mailto:general-boun...@developer.marklogic.com>>
 on behalf of Asitmohan Nautiyal 
<asitmoha...@hcl.com<mailto:asitmoha...@hcl.com>>

Sent: Monday, May 4, 2015 4:40 PM

To: MarkLogic Developer Discussion

Subject: Re: [MarkLogic Dev General] Dynamic order by



Hi Pragya,



try below sample code



let $sorting :=<a> <sorting>

    <columnAlias>Currency</columnAlias>

</sorting>

<sorting>

<sort>desc</sort>

    <columnAlias>AgreementType</columnAlias>

</sorting>

<sorting>

    <sort>asc</sort>

    <columnAlias>CollectionNo</columnAlias>

</sorting></a>



let $results :=

<report>

    <columns>

        <title>Currency</title>

        <title>AgreementType</title>

        <title>CollectionNo</title>

    </columns>

    <results>

        <result>

            <Currency>US dollar</Currency>

            <AgreementType>abc</AgreementType>

            <CollectionNo>0000050</CollectionNo>

        </result>

        <result>

            <Currency>Pound sterling</Currency>

            <AgreementType>xyz</AgreementType>

            <CollectionNo>0000048</CollectionNo>

        </result>

        <result>

            <Currency>Euro</Currency>

            <AgreementType>ebf</AgreementType>

            <CollectionNo>0000049</CollectionNo>

        </result>

    </results>

</report>



return if($sorting/sorting/sort) then

for $each in $results//results/result

order by $each/AgreementType descending , $each/CollectionNo ascending return 
$each (: modify as per your business requirement :) else $results





Regards,

Asit Nautiyal

________________________________

From: 
general-boun...@developer.marklogic.com<mailto:general-boun...@developer.marklogic.com>
 [general-boun...@developer.marklogic.com] on behalf of Kapoor, Pragya 
[pkapo...@innodata.com]

Sent: Monday, May 04, 2015 3:21 PM

To: MarkLogic Developer Discussion

Subject: [MarkLogic Dev General] Dynamic order by





Hi,



I need to sort the $results based on element columnAlias in $sorting.



for eg :

In the below scenario, I want to first sort the $results with 
AgreementType(desc) and then with CollectionNo(asc).If there is not <sort> 
element in $sorting/sorting then do not use that element <columnAlias> for 
sorting.

Moreover the elements in $sorting & $results will be dynamic and not fixed.



let $sorting :=<a> <sorting>

    <columnAlias>Currency</columnAlias>

</sorting>

<sorting>

<sort>desc</sort>

    <columnAlias>AgreementType</columnAlias>

</sorting>

<sorting>

    <sort>asc</sort>

    <columnAlias>CollectionNo</columnAlias>

</sorting></a>



let $results :=

<report>

    <columns>

        <title>Currency</title>

        <title>AgreementType</title>

        <title>CollectionNo</title>

    </columns>

    <results>

        <result>

            <Currency>US dollar</Currency>

            <AgreementType>abc</AgreementType>

            <CollectionNo>0000050</CollectionNo>

        </result>

        <result>

            <Currency>Pound sterling</Currency>

            <AgreementType>xyz</AgreementType>

            <CollectionNo>0000048</CollectionNo>

        </result>

        <result>

            <Currency>Euro</Currency>

            <AgreementType>ebf</AgreementType>

            <CollectionNo>0000049</CollectionNo>

        </result>

    </results>

</report>



Thanks

Pragya



?





"This e-mail and any attachments transmitted with it are for the sole use of 
the intended recipient(s) and may contain confidential , proprietary or 
privileged information. If you are not the intended recipient, please contact 
the sender by reply e-mail and destroy all copies of the original message. Any 
unauthorized review, use, disclosure, dissemination, forwarding, printing or 
copying of this e-mail or any action taken in reliance on this e-mail is 
strictly prohibited and may be unlawful."





::DISCLAIMER::

----------------------------------------------------------------------------------------------------------------------------------------------------

The contents of this e-mail and any attachment(s) are confidential and intended 
for the named recipient(s) only.

E-mail transmission is not guaranteed to be secure or error-free as information 
could be intercepted, corrupted, lost, destroyed, arrive late or incomplete, or 
may contain viruses in transmission. The e mail and its contents (with or 
without referred errors) shall therefore not attach any liability on the 
originator or HCL or its affiliates.

Views or opinions, if any, presented in this email are solely those of the 
author and may not necessarily reflect the views or opinions of HCL or its 
affiliates. Any form of reproduction, dissemination, copying, disclosure, 
modification, distribution and / or publication of this message without the 
prior written consent of authorized representative of HCL is strictly 
prohibited. If you have received this email in error please delete it and 
notify the sender immediately.

Before opening any email and/or attachments, please check them for viruses and 
other defects.

----------------------------------------------------------------------------------------------------------------------------------------------------

"This e-mail and any attachments transmitted with it are for the sole use of 
the intended recipient(s) and may contain confidential , proprietary or 
privileged information. If you are not the intended recipient, please contact 
the sender by reply e-mail and destroy all copies of the original message. Any 
unauthorized review, use, disclosure, dissemination, forwarding, printing or 
copying of this e-mail or any action taken in reliance on this e-mail is 
strictly prohibited and may be unlawful."

-------------- next part --------------

An HTML attachment was scrubbed...

URL: 
http://developer.marklogic.com/pipermail/general/attachments/20150505/227a8999/attachment.html



------------------------------



_______________________________________________

General mailing list

General@developer.marklogic.com<mailto:General@developer.marklogic.com>

Manage your subscription at:

http://developer.marklogic.com/mailman/listinfo/general





End of General Digest, Vol 131, Issue 27

****************************************

_______________________________________________

General mailing list

General@developer.marklogic.com<mailto:General@developer.marklogic.com>

Manage your subscription at:

http://developer.marklogic.com/mailman/listinfo/general
_______________________________________________
General mailing list
General@developer.marklogic.com
Manage your subscription at: 
http://developer.marklogic.com/mailman/listinfo/general

Reply via email to