Search code examples
javascriptmarklogic

strange xdmp.eval() toObject() issue in Marklogic 9


So I have the following issue, I need to update a array in a JSON document. It is a document that captures project settings, members of the project can read the project document but not update it.

I need to first read the document but is a different transaction, extract the members array and go on.

Now the JSON object I get back from the xdmp.eval() cannot find the array, the JSON object directly from the cts.doc() does ...?

Example project doc at uri '/projects/12345.json':

{
"name": "project01",
"description": "example project", 
"id": "12345", 
"members": [
{
"name": "user01", 
"role": "owner", 
"uid": "234"
}, 
{
"name": "user02", 
"role": "member", 
"uid": "123"
}
] 
}

My javascript query:

var pid = 12345;
// uri to project doc
var pUri = '/projects/' + pid + '.json'

// alternative to not lock project doc
var options = {
             "isolation" : "different-transaction"
              }

//var prjObj = xdmp.eval('cts.doc("' + pUri + '")',null,options).toObject()[0]
//var prjObj = xdmp.eval('cts.doc("' + pUri + '").toObject()',null,options)
var prjObj = cts.doc(pUri).toObject()

prjObj.members

gives back the members array as expected but

// cast eval result to object
var prjObj = xdmp.eval('cts.doc("' + pUri + '")',null,options).toObject()[0]
// cast doc to object inside eval
var prjObj = xdmp.eval('cts.doc("' + pUri + '").toObject()',null,options);
// end code

But returned objects can not find the members array...

now what?


Solution

  • xdmp.eval() is returning a sequence of 1 document-node() objects.

    When you invoke .toObject() on that sequence, it is converted into an array with one document-node(), and then [0] is selecting that document-node().

    You could then then use .toObject() to convert the document node into a JavaScript object:

    var prjObj = xdmp.eval('cts.doc("' + pUri + '")',null,options).toObject()[0].toObject()
    

    Alternatively, you could select the first item from the result sequence using fn.head(), and then convert that document-node() into a JavaScript object

    var prjObj = fn.head(xdmp.eval('cts.doc("' + pUri + '")',null,options)).toObject()
    

    and then you can use prjObj.members to address the members array.