JavaScript Multi-statement Transaction in Marklogi

2019-08-20 23:13发布

问题:

I wanted to write a multi-statement transaction in server-side JavaScript in marklogic. What I wanted to achieve is, do an update transaction and then write a query statement which queries for the updated document and confirm that the update is visible within the transaction and finally do a rollback. By doing the rollback, I wanted to confirm that the update made within the transaction is not visible outside the transaction and it is visible within the transaction. I wrote a code both in Xquery as well as serverside JavaScript inorder to achieve this using xdmp:eval/xdmp.eval. I was able to successfully achieve it using Xquery but not in serverside Javascript.

Following is my Xquery code:

xquery version "1.0-ml";
declare option xdmp:transaction-mode "update";

let $query :=
  'xquery version "1.0-ml";
   xdmp:document-insert("/docs/first.json", <myData/>)
  '
return xdmp:eval(
  $query, (),
  <options xmlns="xdmp:eval">
    <isolation>same-statement</isolation>
  </options>);

if (fn:doc("/docs/first.json"))
then ("VISIBLE")
else ("NOT VISIBLE");

xdmp:rollback()

Below is my serverside JavaScript code:

declareUpdate();
var query = 'declareUpdate(); xdmp.documentInsert("/docs/first.json",{"first": 1}); '
xdmp.eval(query,null,{isolation:'same-statement'})

fn.doc("/docs/first.json")

if (fn.doc("/docs/first.json"))
var result = ("visible")
else var result = ("not visible");

xdmp.rollback()
result

I am executing both these codes through Query Console. I am expecting to see the result "visible" in both cases. But when running the serverside JavaScript code, it is throwing me error: [javascript] TypeError: Cannot read property 'result' of null due to xdmp.rollback and not able see the value in variable 'result'

Can someone please correct what is going wrong in my serverside javascript code?

回答1:

In both SJS and XQuery, the approach to inspect the result of a transaction is to eval both the transaction and the inspection in statements that are different from the choreographing outer statement.

(The XQuery semicolon syntax separates statements that execute in different transactions -- the equivalent of a series of evals without a choreographing outer statement.)

Something similar to the following should work:

'use strict';
xdmp.eval(
    'declareUpdate(); xdmp.documentInsert("/docs/first.json",{"first": 1});',
    null,
    {isolation:'different-transaction'});
const doc = xdmp.eval(
    'cts.doc("/docs/first.json")',
    null,
    {isolation:'different-transaction'});
fn.exists(doc);

That said, it's unnecessary to verify document insertion. If the insertion fails, the server throws an error.

It's also unnecessary to use a different transaction to read the inserted document in order to return it. Just return the document after the xdmp.insert() call.

Hoping that helps,