使用Marklogic 8触发器来管理三元组

时间:2016-09-09 13:27:00

标签: triggers semantics marklogic

我有一个用例,我想在每次从MarkLogic添加或删除三元组时发送通知。通知应包含这些三元组,并应说明它们是否已添加或删除。

我在MarkLogic triggers guide中没有发现任何关于它如何与(托管)三元组合作的提及。有没有办法编写触发器模块,以便对于修改后的文档(包含托管三元组),将新版本与旧版本进行比较,以确定添加和删除的内容,并发送包含这些更改的HTTP请求?

我理解doc($ trgr:uri)会给我这个文档的最新状态 - 但有没有办法在更改之前检索以前的版本?我是MarkLogic和Xquery的新手,因此非常感谢一些指导。谢谢!

2 个答案:

答案 0 :(得分:2)

我认为你只能通过一种方式实现这一目标:

  • 使用pre-commit触发器
  • 使用xdmp:eval isolation different-transaction获取原始文档

类似的东西:

xquery version "1.0-ml";

import module namespace trgr = "http://marklogic.com/xdmp/triggers" at "/MarkLogic/triggers.xqy";

declare variable $trgr:uri as xs:string external;

xdmp:log("Triggered processing of " || $trgr:uri || ".."),

xdmp:log(xdmp:eval('doc("'||$trgr:uri||'")', (), <options xmlns="xdmp:eval"><isolation>different-transaction</isolation></options>)),
xdmp:log(doc($trgr:uri))

我运行了一个快速测试,其中一个触发器用于集合'test'。然后我在/test.xml中插入了一个内容为<test>a</test>的doc,并没有将它添加到集合测试中。然后我用<test>b</test>更新了文档,并将其添加到集合测试以激活触发器。它记录了a和b ..

这显示了如何获取原始文档和更新文档。确定差异本身就是一个挑战..

HTH!

答案 1 :(得分:2)

非常感谢@grtjn提供访问更改前文档的方法。为了确定文档之间的差异,我发现了一种受此blog post启发的方式。我发现工作的解决方案看起来像这样:

xquery version '1.0-ml';
import module namespace trgr='http://marklogic.com/xdmp/triggers' at '/MarkLogic/triggers.xqy';

declare function local:diff($seq1 as item()*, $seq2 as item()*) as item()* {
    let $map1 := map:new($seq1 ! map:entry(fn:string(.), .))
    let $map2 := map:new($seq2 ! map:entry(fn:string(.), .))
    return map:keys($map1 - $map2) ! map:get($map1,.)
};

declare variable $trgr:uri as xs:string external;
declare variable $after := doc($trgr:uri)/sem:triples/sem:triple;
declare variable $before := xdmp:eval('doc("'||$trgr:uri||'")', (),
    <options xmlns="xdmp:eval"><isolation>different-transaction</isolation></options>)/sem:triples/sem:triple;

declare variable $added_triples := local:diff($after, $before);
declare variable $added_graph := xdmp:document-get-collections($trgr:uri);

declare variable $deleted_triples := local:diff($before, $after);
declare variable $deleted_graph := xdmp:eval('xdmp:document-get-collections("'||$trgr:uri||'")', (),
    <options xmlns="xdmp:eval"><isolation>different-transaction</isolation></options>);


xdmp:log(fn:concat('***** Trigger processing:  ', $trgr:uri, '*****')),
xdmp:log('***** added triples *****'),
xdmp:log($added_graph),
xdmp:log($added_triples),
xdmp:log('***** deleted triples *****'),
xdmp:log($deleted_graph),
xdmp:log($deleted_triples)

我创建了3个pre-commit个触发器,每个trgr:document-content选项一个:createmodifydelete,都调用了上述模块。 SPARQL Update查询将导致上述模块触发一次或多次,打印添加和删除的三元组列表。

观察结果:

  • 单个SPARQL Update语句可以创建,修改和删除多个文档,因此会多次触发该模块。
  • INSERT语句似乎总是创建新文档,因此您将永远不会在同一个调用中添加三元组和删除的三元组。
  • 代码假定文档只有一个集合,这是托管三元组的命名图。如果每个文档有多个集合,则需要额外的工作。