插入文档后无法立即读取

Suk*_*esh 1 marklogic

我试图在插入文档后立即阅读该文档。当我尝试阅读文档时,我认为文档的插入正在进行中。请让我知道如何使用下面的代码片段获得结果。执行下面的代码,出现错误 'Cannot read property 'xpath' of null' 。

declareUpdate();
xdmp.documentInsert("abc.xml",cts.doc("xyz.xml"));
return cts.doc("abc.xml").xpath("/root");
Run Code Online (Sandbox Code Playgroud)

Dav*_*nis 5

好的。这是一个工作示例(假设 xyz.xml 已在数据库中)。但请看下面的例子。

declareUpdate();

xdmp.invokeFunction(function(){
    xdmp.documentInsert("abc.xml",cts.doc("xyz.xml"));
  },
  {
    transactionMode:"update-auto-commit",
    isolation:"different-transaction"
  }                   
);


cts.doc("abc.xml").xpath("/root");
Run Code Online (Sandbox Code Playgroud)

这肯定是这样一种情况:简单地复制和粘贴上面的代码而不了解其背后的内容并不是一个好主意。不花时间去理解 MarkLogic 中的交易只会让你感到沮丧和受伤。排除这些之后,下面有一些好处:

进一步阅读:

示例解释: 我们需要将文档插入放入调用函数中的原因是我们需要在单独的事务中运行它。这与 MarkLogic 的多版本并发控制 (MVCC) 有关。基本上,在我们的票据开始处理时该文档并不存在。通过使用更新和不同事务的组合,我们允许调用代码可以使用该事务的已提交文档。

但要小心您决定何时以及如何使用它。例如,如果我们在当前事务中读取 xyz.xml,然后尝试在调用的函数中更新文档,则会出现死锁 - 第一个事务等待第二个事务,第二个事务等待第一个事务。

痛苦世界的例子:

declareUpdate();

let doc  = cts.doc("xyz.xml");

xdmp.invokeFunction(function(){
   xdmp.nodeInsertChild(cts.doc("xyz.xml").xpath("/root"),
   fn.head(xdmp.unquote('<a>b</a>')).root);
},
  {
    transactionMode:"update-auto-commit",
    isolation:"different-transaction"
  }                   
);

cts.doc("xyz.xml");
Run Code Online (Sandbox Code Playgroud)

上面的看起来很无辜。它看起来合乎逻辑 - 更新另一个事务中的文档,然后读取它。不……第一次阅读会导致先有鸡还是先有蛋的情况。这笔交易永远不会完成。您可以添加该选项 preventDeadlocks: true。这至少会抛出 n 个错误而不是挂起。这个故事的寓意 - 尽早理解交易并理解为什么示例 1 有效而类似的示例 2 无效。