Transactions 标记逻辑删除>;插入>;伙伴关系就新文件采取行动

Transactions 标记逻辑删除>;插入>;伙伴关系就新文件采取行动,transactions,xquery,marklogic,Transactions,Xquery,Marklogic,请参阅下面的更新 我有以下问题:我们正在将(数百万)文档(tweets)收集到ML中,在insert中,我们有一个cpf作业,为每个文档创建元数据。更精确的是,它根据位置(如果存在位置或坐标)添加地理标记 现在我们有了一个数据库,它一直在收集推文,而地理标记器没有激活。我们希望通过删除并重新插入尚未具有适当元数据geotag元素的每个文档来处理此cpf作业中存储的tweet。 然后cpf完成它的工作,并对“新”文档进行地理标记 我们已经编写了以下代码来删除和插入文档,但是我们得到了一个XDMP-

请参阅下面的更新

我有以下问题:我们正在将(数百万)文档(tweets)收集到ML中,在insert中,我们有一个cpf作业,为每个文档创建元数据。更精确的是,它根据位置(如果存在位置或坐标)添加地理标记

现在我们有了一个数据库,它一直在收集推文,而地理标记器没有激活。我们希望通过删除并重新插入尚未具有适当元数据geotag元素的每个文档来处理此cpf作业中存储的tweet。 然后cpf完成它的工作,并对“新”文档进行地理标记

我们已经编写了以下代码来删除和插入文档,但是我们得到了一个XDMP-CONFLICTUPDATES错误。我一直在阅读有关交易的书籍,并尝试了几种方法,即“;”诀窍。在xdmp:eval中包装,或在xdmp:spawn的两个单独函数调用中拆分delete和insert

还是不走运

spawn-rename.xqy

xquery version "1.0-ml";

declare namespace j = "http://marklogic.com/xdmp/json/basic";
declare variable $to_process external;

declare function local:document-rename(
   $old-uri as xs:string, $new-uri as xs:string)
  as empty-sequence()
{
    (:xdmp:set-transaction-mode("update"),:)
    xdmp:eval(xdmp:document-delete($old-uri)),
    (:xdmp:commit():)

    let $permissions := xdmp:document-get-permissions($old-uri)
    let $collections := xdmp:document-get-collections($old-uri)
    return xdmp:document-insert(
      $new-uri, doc($old-uri),
      if ($permissions) then $permissions
      else xdmp:default-permissions(),
      if ($collections) then $collections
      else xdmp:default-collections(),
      xdmp:document-get-quality($old-uri)
    )
};

for $d in map:keys($to_process)
let $rename := local:document-rename($d, map:get($to_process,$d))
return true()
要为我们使用的特定文档集运行作业,请执行以下操作:

xquery version "1.0-ml";
declare namespace j = "http://marklogic.com/xdmp/json/basic";
declare namespace dikw = 'http://www.example.com/dikw_functions.xqy';
import module namespace json = "http://marklogic.com/xdmp/json" at "/MarkLogic/json/json.xqy";

let $foo := cts:uris((),(), cts:not-query(cts:element-query(xs:QName("j:dikwmetadata"), cts:element-query(xs:QName("j:data"), cts:and-query(())))))
let $items := cts:uri-match("/twitter/403580066367815680.json") (:any valid uri or set of uris:)

let $map := map:map()

    let $f := doc($items[1])
    let $id := $f/j:json/j:id/text()
    let $oldUri := xdmp:node-uri($f)
    let $newUri := fn:concat("/twitter/", $f/j:json/j:id/text(), ".json")
    let $put := map:put($map,$oldUri,$newUri)

    let $spawn := xdmp:spawn("/Modules/DIKW/spawn-rename-split.xqy", (xs:QName("to_process"), $map))

return ($oldUri, " - ", $newUri) 
问题:

如何设置代码,使其在单独的事务中首先删除地图中的文档,然后再将其插入,以便cpf可以进行地理标记


更新

根据grtjn的评论(到目前为止是thx!) 我尝试重写代码,如下所示:

xquery version "1.0-ml";
declare namespace j = "http://marklogic.com/xdmp/json/basic";

let $entries := cts:uri-match("//twitter/*")
let $entry-count := fn:count($entries)

let $transaction-size := 100 (: batch size $max :)
let $total-transactions := ceiling($entry-count div $transaction-size)

(: set total documents and total transactions so UI displays collecting :)
(: skip 84 85
let $set-total := infodev:ticket-set-total-documents($ticket-id, $entry-count)
let $set-trans := infodev:ticket-set-total-transactions($ticket-id,$total-transactions)
:)
    (: create transactions by breaking document set into maps
each maps's documents are saved to the db in their own transaction :)
let $transactions :=
    for $i at $index in 1 to $total-transactions
    let $map := map:map()
    let $start := (($i -1) *$transaction-size) + 1
    let $finish := min((($start - 1 + $transaction-size),$entry-count))
    let $put :=
        for $entry in ($entries)[$start to $finish]
        (: 96
        let $id := fn:concat(fn:string($entry/atom:id),".xml")
        :)
        let $id := fn:doc($entry)/j:json/j:id/text()
        return map:put($map,$id,$entry)
    return $map

(: the callback function for ingest 
skip 101 let $function := xdmp:function(xs:QName("feed:process-file"))
:)
let $ingestion :=
    for $transaction at $index in $transactions
    return true()
    return $ingestion (: this second return statement seems odd? :)
    (: do spawn here? :)
    (: xdmp:spawn("/modules/spawn-move.xqy", (xs:QName("to_process"), $map)) :)
现在我很困惑,为了让这个“有效”,我需要添加上一个似乎不正确的报税表。此外,如果按原样运行查询并返回超时错误,我还试图弄清楚到底发生了什么。 我想首先了解交易的实际用途。 对不起,我的无知,但似乎执行(相对简单的)任务重命名一些文件看起来不是那么简单

为完整起见,请在此处输入my spawn-move.qry:

xquery version "1.0-ml";

declare namespace j = "http://marklogic.com/xdmp/json/basic";
declare variable $to_process external;


declare function local:document-move(
   $id as xs:string, $doc as xs:string)
  as empty-sequence()
{
    let $newUri := fn:concat("/twitter/", $id, ".json")
    let $ins := xdmp:document-insert($newUri,fn:doc($doc))
    let $del := xdmp:document-delete($doc) 
    return true()
};

for $d in map:keys($to_process)
let $move := local:document-move($d, map:get($to_process,$d))
return true()

在您的示例中,似乎您正试图在同一步骤中删除文档并将其写入同一URI。您可以通过xdmp:commit()解决这个问题。但是,另一种解决方案是,首先在一批中重命名文档(将它们全部移到一边),然后在完成后,将它们分批移回原处。

我怀疑您实际上不是在重命名文档,而是在重新插入它们。如果
$old uri
$new uri
相同,则您引用的
重命名
函数不会预料到这种情况,并且会执行多余的
文档删除
。在delete周围添加
if
,在这种情况下跳过它。保留所有其他内容以保留权限、集合、质量和属性。
文档插入
功能已经在实际插入之前删除了预先存在的文档。另见:

<>你也可以考虑添加一点逻辑来做多个产卵。理想情况下,根据硬件和林配置,您希望以100到500个文档为一批重新插入文档。有一个很好的例子说明了如何在github上的infostudio收集器中计算“事务”(从第80行开始):

<>您也可以考虑在这些事务中做地理工作,而不是将其委托给CPF。但是,如果您的地理位置查找涉及到外部调用,例如可能很慢,那么请坚持使用CPF


实际上,如果您已将CPF管道配置为处理诸如creates之类的更新(这是默认配置),则只需重新插入文档即可:


xdmp:document insert($d,doc($d))

thx用于响应,我尝试了xdmp:commit()(请参见我尝试的第一个代码,但注释为in out),但这不起作用,它需要一个分号来结束事务,而您会遇到各种我不理解的问题。我正在为你的第二个方向努力,但我觉得这似乎很缓慢?另外,cpf过程似乎非常缓慢。有没有加快cpf的提示?可能会帮助您理解
xdmp:commit
和分号.thx grtjn,我有两个用例,一个确实只是重新插入现有文档,另一个是我在错误的uri中插入了500.000个文档,从“/twitter/”开始,而不是“/twitter/”,因此查看“/twitter/”的cpf作业遗漏了这些文档。我正在寻找处理这些问题的方法。一般来说,我不知道如何在ml中完成这类工作,而不会遇到查询超时等问题。当指针指向第80行时,我无法理解插入和运行它所需的内容,以便一次处理500000个文档。@hugo koopmans将第80行复制到104行,定义一个包含所有URI的变量$entries(您有$foo/$items),使用条目数定义变量$entry count,将$max替换为100(这是您的批处理大小),跳过第84/85/96/101行,编辑第97行,将$entry作为键和一个伪值放在映射中,并在第104行之后添加您的spawn。这样,您可以在spawn之前跳过计算$newURI,但最好在spawed任务中改为这样做。