我正在尝试在插入文档后阅读它。我想在我尝试阅读时,文档的插入正在进行中。请告诉我如何使用以下代码段获得结果。执行下面的代码,给我错误'无法读取属性' xpath' of null'
declareUpdate();
xdmp.documentInsert("abc.xml",cts.doc("xyz.xml"));
return cts.doc("abc.xml").xpath("/root");
答案 0 :(得分:4)
行。这是一个工作示例(假设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");
这肯定是那些简单地复制和粘贴上面的代码而不了解它背后的内容并不是一个好主意的时代之一。花时间了解MarkLogic中的交易只会让你感到沮丧并处于一个受伤的世界。除此之外,一些好东西在下面:
进一步阅读:
示例解释: 我们需要将document-insert放入invoke函数的原因是因为我们需要在单独的事务中运行它。这与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");
以上看起来无辜。它看起来合乎逻辑 - 更新另一个事务中的doc然后阅读它。不......第一次阅读导致鸡/蛋情况。此交易永远不会完成。您可以添加选项preventDeadlocks: true
。这将至少抛出n错误而不是挂起。故事的道德 - 早期理解交易并理解为什么示例1起作用而类似示例2不起作用。
答案 1 :(得分:1)
此问题与事务边界有关。事务中的所有更新都会在事务结束时提交 - 并在数据库中生效。为了在一个事务中查看更新结果,您必须在上一个事务完成后开始的单独事务中从数据库中读取。
答案 2 :(得分:1)
我建议避免调用等,除非你没有其他选择。您是否认为只是相信插入将起作用,并且您返回'xyz.xml'的内容?
let doc = doc("xyz.xml");
xdmp.documentInsert("abc.xml", doc);
doc.xpath("/root");
HTH!