我有一个要求,我要遍历10,000,000个文档,并对每个文档进行一些操作并将一些值存储在'/count.xml'中。当我遍历第二个文档时,我用更新后的值更新了'/count.xml'
目前这就是我在做什么,这里的总记录为10,000,000
let $total-records := xdmp:estimate(cts:search( //some code))
let $batch-size := 5000
let $pagination := 0
let $bs :=
for $records in 1 to fn:ceiling($total-records div $batch-size )
let $start := fn:sum($pagination + 1)
let $end := fn:sum($batch-size + $pagination)
let $_ := xdmp:set($pagination, $end)
return
xdmp:spawn-function
(
function() {
for $each in cts:search( //some code)[$start to $end]
return //some operation and update '/count.xml' with some updated values
},
<options xmlns="xdmp:eval"><commit>auto</commit><update>true</update</options>
)
let $doc := doc("/count.xml")
return ()
所以这里的问题是,在所有文档都经过迭代之后,我需要读取'/count.xml'文件,但是对于上面的代码,使用了spawn任务
让$ doc:= doc(“ / count.xml”)
不会是最新的,因为上面的生成任务将在不同的线程上运行。
我需要一个解决方案
让$ doc:= doc(“ / count.xml”)
等待直到所有派生任务完成。
我碰到了
<result>{fn:true()}</result>
选项也一样,但是我不知道它是否可以工作,因为变量
$ bs
没有在任何地方使用,并且文档说“当调用请求在任何操作中使用future值时,它将自动等待派生任务完成并使用结果。”
还有其他替代方法
让$ doc:= doc(“ / count.xml”)
仅在所有派生任务完成后执行行
答案 0 :(得分:2)
要处理1000万个文档,您可能需要生成1000个文档的10.000批。我认为这在MarkLogic内部不能很好地工作。
我建议您研究一下MarkLogic的内置聚合功能。例如参见cts:sum-aggregate
。您可能可以预先计算每个文档的中间结果,然后可以在运行时使用这些汇总功能进行汇总。那绝对是性能最高的,并且扩展性最好。
替代方法是从MarkLogic外部协调您的计算。否则,您要么淹没任务队列,要么陷入超时限制,或者两者兼而有之。 Corb2和DMSDK之类的工具可能对此有所帮助。
注意:您确实可以通过使用<result>
选项使生成等待结果,但是可以使用<result>true</result>
或<result>{fn:true()}</result>
(请注意fn:true后面的括号,它是一个函数)。
HTH!
答案 1 :(得分:2)
给定的要求是,不能区分在10,mil个文档中编写一次 query 的最终结果与编写1个文档的 query 之后的结果之间的区别一次。由于您的示例不写入查询的文档,因此无需生成或在单独的线程或事务中运行它,就像HTH所说的那样,您也可以使用聚合函数对整个集合进行单个查询,计算最终结果并存储在1个操作中。这很可能会很快运行(或可以做到)。
如果实际上是必须查询每个单个文档的要求,则依次写入另一个共享文档-这只能通过依次使用单独的事务来观察。它的速度将极其缓慢,几乎肯定会比调用事务的超时时间更长。这意味着您必须从外部进行编排-如果 requirement 是同一调用者启动该过程并完成该过程(高度实现的特定要求是,如果为true,则可能会除了给出的含义外,还有其他含义。
可以实现但仍然非常慢的事情是对更新的共享文档进行外部查询民意调查,并在工作完成后返回“成功”。 但是同样,对于这么多的文档,如果您要为每个文档强制执行一次写事务,则它会花费更长的时间(或者不容易保证不会花费更长的时间),因此单个事务超时必须从“外部”调用。
在这里,我建议您重新检查需求,以确定所需的核心功能/结果,以及是否确实需要严格按照规定实施与要实现所需结果的更高性能的实施。 如果所需的核心功能是在文档更新时对每个查询进行“检查点”,则还需要考虑其他含义,例如事务回滚。