To clarify the other Reponses, there are several distinct issues to consider.

1) appending documents - in-memory vs DB.
There is no Database level document append, every change you make to a document 
requires reading/modify/write and creates a new document.  In a case as you 
describe, that is not a good approach for many reasons, performance , IO , 
possible locking issues etc instead you should create the final document image 
in memory.

2) transaction locking.
Very important to not mix a large search in  the same transaction as an update,
however you can fairly easily do the update in the same 'code' but as a 
separate transaction by 
making use of xdmp:invoke() or xdmp:invoke-function()
I like invoke-function because you don't need a separate XQuery file
See:
https://docs.marklogic.com/xdmp:invoke-function
Use the <isolation>different-transaction</isolation> option as discussed here;
https://docs.marklogic.com/xdmp:eval




3) How to create a document iterative in memory.
The suggestions given are excellent.  
An alternative is to directly use the 'functional programming' paradigm that 
XQuery is based on - this is fundamentally different the 'procedural 
programming' and can take a while to 'sink in' when one is used to procedural 
languages.  The core idea is that in functional programming languages there 
really is not 'iteration' in the same sense. You cannot actually update a 
variable (a few exceptions with some special internal functions).  
Instead you create the final result 'bottom up' as a single expression.  This 
usually involves recursion instead of iteration.

E.g. Where you might naturally think like this:

let $doc :=  <doc/> 
return    
for $row in cts:search() ... 
     add-result( $doc,  $row )
return $doc

That doesn't actually work.  You use some techniques to get  close but they 
tend to be inefficient and clumsy in loops, for example  'add-result' can 
return a new copy of $doc every time its called like 
   $doc := add-result( $doc , $row )
This is what the various in-memory functions do.
But then it is still a bit tricky to find the 'last' $doc returned,
because you are not actually modifying the same $doc variable as in 'let $doc 
...'  instead a new variable named '$doc' is created each time (and then 
abandoned) so you're not actually passing the new '$doc' variable into the loop 
nor getting it at the end. 
  'Mapping' iterative procedural style to functional programming can be 
frustrating until you realize you need to think of the problem differently.

Recursion is generally the 'natural' solution.  And since almost every 
operation on sequences uses 'lazy evaluation' it can be much more efficient 
than you think - quite the opposite.  In ML XQuery, passing references to 
sequences of arbitrary length is very efficient - it is only passing a single 
reference not a copy, whereas incrementally creating documents by inserting one 
element at a time is very inefficient - because it has to recreate the entire 
document for each insertion.    So with Recursion you solve both problems - 

E.g. 
For simple cases this is how one can efficiently make a document out of a 
sequence of data. 
Note that this never has to update data in place

   let  $doc :=
      <doc>{ 
           for $r in := cts:search( ... )
          return 
                   create-element-from-one-row( $r )
     }</doc>

For more complex needs a recursive function like this can be used, 
Note that by producing not the full document each call its much faster
and easier to write.

declare function local:addRow(  $data as element(old) * , $new as element(new)* 
) 
  as  element(new) * 
{
     if( empty( $data ) ) then $new  (: done ! :)
    else   (:  some more complex logic here if you want to reorder the results 
or look at previous values first :)
        local:addRow( $data[position() gt 1] ,  
            <row>{ create-row-from-data( $data[1] ) }</row>  )
};


(: creates full document in one expression :)
let $doc := <doc>{ local:addRow(  cts:search(...) , () ) } </doc>




-----------------------------------------------------------------------------
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 Christopher Hamlin
Sent: Thursday, June 18, 2015 8:42 PM
To: MarkLogic Developer Discussion
Subject: Re: [MarkLogic Dev General] Generating Reports in ML

On Thu, Jun 18, 2015 at 4:55 PM, Kari Cowan <kco...@alm.com> wrote:
> To be clear, I can take a single result and return it into a 
> xdmp:document-insert statement – is there a method available to 
> iteratively append to that document?
>

You can use the node insert calls as Danny suggested.  But if you do, beware of 
multiple changes to the same document giving you conflicting-updates errors, if 
you mean to make >1 change to the same document in the same transaction.  In 
that case you can just create a new document in memory with all the changes and 
reinsert it.  There's also a library that lets you make changes to in-memory 
documents.

/ch
_______________________________________________
General mailing list
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