1

I am using below xquery to copy documents from one database to another in MarkLogic. Along with copying my requirement is to remove those documents which are successfully copied. I cannot remove the collection fully as some of the documents may not get copied as they fails to get copied due to template document errors which are present in the target database.

Is there a way to get the list of the documents which are not copied and got failed due to template errors and retain them in the source database and delete the rest of them.

Here is my xquery to copy the documents -

xquery version "1.0-ml";
for $doc in cts:search(doc(), cts:collection-query('Collection1'))
let $docuri := $doc/base-uri()
let $collections := xdmp:document-get-collections($docuri)
let $permissions := xdmp:document-get-permissions($docuri)
let $document-insert-options := 
  <options xmlns="xdmp:document-insert">  
    <permissions>{$permissions}</permissions>
    <collections>{
        <collection>{$collections}</collection>
        }
        </collections> 
  </options>
let $db-name := "STAGING"  
let $invoke-function-options := 
  <options xmlns="xdmp:eval">
    <database>{ xdmp:database($db-name) }</database>
    <commit>auto</commit>
  </options>
return
 xdmp:invoke-function(
   function(){ xdmp:document-insert($docuri, $doc, $document-insert-options)},
   $invoke-function-options
 ); 
 

1 Answers1

2

You need to catch any error that occurs and handle it or if no error occurs then proceed with deleting the original document.

The KnowledgeBase suggests:

...execute the updates in an xdmp:eval() or an xdmp-invoke()with different-transaction isolation, and wrap the eval or invoke inside a try/catch block. In this way, The commit time errors can be caught.

To implement this change your return to:

return
 try {
  let $_ := xdmp:invoke-function(
   function(){ xdmp:document-insert($docuri, $doc, $document-insert-options)},
     $invoke-function-options
   )
  return xdmp:document-delete($docuri)
 }
 catch($exception)
 {
  (: Handle the error :)
  xdmp:rethrow() (: To stop processing and stop the application at this point if desired :) 
 }

In this code the document-delete won't run if an exception is thrown from invoke-function. Instead, execution will jump into the catch block.

An alternative approach is to do the deletes in a separate operation. You could get a list of URIs from Database 2 and then delete anything in that list that exists in Database 1.

A second alternative approach is to copy the data over using database replication and then deleting the original database once fully replicated.

A third alternative approach is to copy the data over using a backup and then deleting the original database.

grtjn
  • 20,254
  • 1
  • 24
  • 35
Rob S.
  • 3,599
  • 6
  • 30
  • 39
  • Thanks , but my objective is also to retain the files which are not copied and only to delete the ones which are successfully copied . How can I get that list which are NOT COPIED / COPIED please. – Rashmita Purkayastha Jul 06 '22 at 15:59
  • I can get the list of document uris from each database , but I am not sure how can I make the comparison . What function or how I can I write to see the comparison . If you can help please – Rashmita Purkayastha Jul 06 '22 at 16:04
  • @RashmitaPurkayastha You can use cts:uris() to query for a list of URIs instead of documents within a database. If you want to create a list of failures then just write that into the catch{} block – Rob S. Jul 06 '22 at 16:10