我将如何通过将 420,000 多个文档拆分为 10,000 个文档批次来处理这些文档?
How would I process 420,000+ documents by splitting them up into 10,000 document batches?
我们需要为集合中每个文档的权限添加几个角色。以下是当前代码(针对 pii 进行了更改)。我们将如何更改代码以处理 10,000 个记录批次?那会减少所需的 space 吗?或者有没有更快的方法来更改文档的权限?
declareUpdate();
let aUri = '';
const uris = cts.uris('',[],cts.collectionQuery('DataCollection'));
for (aUri of uris) {
xdmp.documentSetPermissions(
aUri, [
xdmp.permission("data_user_a", "read"),
xdmp.permission("data_user_b", "read")
]
);
};
我们当前遇到错误:
Expanded tree cache full on host marklogic-hostname uri /company/data/document_4534543.json
驱动器上有 75 个空闲空间。
如您所见,尝试在一个事务中处理那么多文档会耗尽扩展树缓存。
分批处理这些更新的最简单方法是将工作生成为在任务服务器上执行的单独事务。通过 XQuery,您可以将 xdmp:spawn-function()
与匿名函数一起使用。
像这样(我会使用小于 10k 的批量大小):
let $page-size := 1000
let $uris := cts:uris('', (), cts:collection-query('DataCollection'))
let $pages := (count($uris) idiv $page-size) + 1
return
for $page in (1 to $pages)
let $start := (($page - 1) * $page-size) + 1
let $end := $page * $page-size
let $uris := subsequence($uris, $start, $end)
return
xdmp:spawn-function(function(){
for $uri in $uris
return
xdmp:document-set-permissions($uri, (
xdmp:permission("data_user_a", "read"),
xdmp:permission("data_user_b", "read")
)
)
})
JavaScript 模块没有 xdmp.spawnFunction()
等价物。不过,您可以调用 xdmp.spawn()
并执行已安装的模块。
但是,尝试在任务服务器上生成大量工作有一些缺点。您的移动速度只能与一个任务服务器一次处理一个事务的速度一样快,并且如果您碰巧使用了太大的批次或碰到了一个口袋,您仍然 运行 有破坏扩展树缓存的风险非常大的文档。
大批量作业更好运行 使用批处理工具,例如 CoRB. It was designed for this purpose. You can adjust the THREAD-COUNT and BATCH-SIZE 选项,并且可以执行您的 JavaScript 模块而无需将它们安装在模块数据库中。
此类作业的示例属性文件如下所示:
THREAD-COUNT=32
URIS-MODULE=INLINE-JAVASCRIPT|const uris = cts.uris('',[],cts.collectionQuery('DataCollection')); fn.insertBefore(uris, 0, fn.count(uris));
PROCESS-MODULE=INLINE-JAVASCRIPT|declareUpdate(); var URI; xdmp.documentSetPermissions(URI, [xdmp.permission("data_user_a", "read"), xdmp.permission("data_user_b", "read")]);
我展示了将代码内嵌在选项文件中,但您可以告诉它使用文件名和 |ADHOC
suffix 或模块数据库中模块的路径从文件中读取。
然后将使用 java 命令、gradle 任务等执行作业
java -cp "lib/*" -DOPTIONS-FILE=my.properties com.marklogic.developer.corb.Manager xcc://username:password@localhost:8000/database
我们需要为集合中每个文档的权限添加几个角色。以下是当前代码(针对 pii 进行了更改)。我们将如何更改代码以处理 10,000 个记录批次?那会减少所需的 space 吗?或者有没有更快的方法来更改文档的权限?
declareUpdate();
let aUri = '';
const uris = cts.uris('',[],cts.collectionQuery('DataCollection'));
for (aUri of uris) {
xdmp.documentSetPermissions(
aUri, [
xdmp.permission("data_user_a", "read"),
xdmp.permission("data_user_b", "read")
]
);
};
我们当前遇到错误:
Expanded tree cache full on host marklogic-hostname uri /company/data/document_4534543.json
驱动器上有 75 个空闲空间。
如您所见,尝试在一个事务中处理那么多文档会耗尽扩展树缓存。
分批处理这些更新的最简单方法是将工作生成为在任务服务器上执行的单独事务。通过 XQuery,您可以将 xdmp:spawn-function()
与匿名函数一起使用。
像这样(我会使用小于 10k 的批量大小):
let $page-size := 1000
let $uris := cts:uris('', (), cts:collection-query('DataCollection'))
let $pages := (count($uris) idiv $page-size) + 1
return
for $page in (1 to $pages)
let $start := (($page - 1) * $page-size) + 1
let $end := $page * $page-size
let $uris := subsequence($uris, $start, $end)
return
xdmp:spawn-function(function(){
for $uri in $uris
return
xdmp:document-set-permissions($uri, (
xdmp:permission("data_user_a", "read"),
xdmp:permission("data_user_b", "read")
)
)
})
JavaScript 模块没有 xdmp.spawnFunction()
等价物。不过,您可以调用 xdmp.spawn()
并执行已安装的模块。
但是,尝试在任务服务器上生成大量工作有一些缺点。您的移动速度只能与一个任务服务器一次处理一个事务的速度一样快,并且如果您碰巧使用了太大的批次或碰到了一个口袋,您仍然 运行 有破坏扩展树缓存的风险非常大的文档。
大批量作业更好运行 使用批处理工具,例如 CoRB. It was designed for this purpose. You can adjust the THREAD-COUNT and BATCH-SIZE 选项,并且可以执行您的 JavaScript 模块而无需将它们安装在模块数据库中。
此类作业的示例属性文件如下所示:
THREAD-COUNT=32
URIS-MODULE=INLINE-JAVASCRIPT|const uris = cts.uris('',[],cts.collectionQuery('DataCollection')); fn.insertBefore(uris, 0, fn.count(uris));
PROCESS-MODULE=INLINE-JAVASCRIPT|declareUpdate(); var URI; xdmp.documentSetPermissions(URI, [xdmp.permission("data_user_a", "read"), xdmp.permission("data_user_b", "read")]);
我展示了将代码内嵌在选项文件中,但您可以告诉它使用文件名和 |ADHOC
suffix 或模块数据库中模块的路径从文件中读取。
然后将使用 java 命令、gradle 任务等执行作业
java -cp "lib/*" -DOPTIONS-FILE=my.properties com.marklogic.developer.corb.Manager xcc://username:password@localhost:8000/database