使用 XQuery 递归复制文件夹
Recursive copy of a folder with XQuery
我必须在 MarkLogic 服务器中复制整个项目文件夹,而不是手动执行,我决定使用递归函数来执行它,但这正在成为我曾经有过的最糟糕的想法。我在交易和语法方面遇到问题,但作为新手,我找不到真正的解决方法。这是我的代码,谢谢你的帮助!
import module namespace dls = "http://marklogic.com/xdmp/dls" at "/MarkLogic/dls.xqy";
declare option xdmp:set-transaction-mode "update";
declare function local:recursive-copy($filesystem as xs:string, $uri as xs:string)
{
for $e in xdmp:filesystem-directory($filesystem)/dir:entry
return
if($e/dir:type/text() = "file")
then dls:document-insert-and-manage($e/dir:filename, fn:false(), $e/dir:pathname)
else
(
xdmp:directory-create(concat(concat($uri, data($e/dir:filename)), "/")),
local:recursive-copy($e/dir:pathname, $uri)
)
};
let $filesystemfolder := 'C:\Users\WB523152\Downloads\expath-ml-console-0.4.0\src'
let $uri := "/expath_console/"
return local:recursive-copy($filesystemfolder, $uri)
MLCP 会很好用。但是,这是我的版本:
declare option xdmp:set-transaction-mode "update";
declare variable $prefix-replace := ('C:/', '/expath_console/');
declare function local:recursive-copy($filesystem as xs:string){
for $e in xdmp:filesystem-directory($filesystem)/dir:entry
return
if($e/dir:type/text() = "file")
then
let $source := $e/dir:pathname/text()
let $dest := fn:replace($source, $prefix-replace[1], $prefix-replace[2])
let $_ := xdmp:document-insert($source,
<options xmlns="xdmp:document-load">
<uri>{$dest}</uri>
</options>)
return <record>
<from>{$source}</from>
<to>{$dest}</to>
</record>
else
local:recursive-copy($e/dir:pathname)
};
let $filesystemfolder := 'C:\Temp'
return <results>{local:recursive-copy($filesystemfolder)}</results>
请注意以下事项:
- 我将示例更改为 C:\Temp 目录
- 输出是 XML 只是因为按照惯例我尝试这样做以防我想分析结果。这实际上是我发现与更新冲突相关的错误的方式。
- 我选择在 URI 上定义一个简单的前缀替换
- 根据您的描述,我认为不需要 DLS
- 我认为在您的用例中不需要显式创建目录
- 您收到冲突更新的原因是您仅使用文件名作为 URI。在整个目录结构中,这些名称不是唯一的 - 因此对相同 URI 的双重插入进行冲突更新。
- 这不是可靠的代码:
- 您必须确保 URI 有效。并非所有文件系统 paths/names 都适用于 URI,因此您需要对此进行测试并在需要时转义字符。
- 大型文件系统会超时,因此分批生成可能很有用。
- 举个例子,我可能会像 XML 中那样收集文档列表,然后通过为每 100 个文档生成一个新任务来处理该列表。这可以通过 xdmp:spawn 函数上的简单循环或使用 @mblakele
的 taskbot 等库来完成
我必须在 MarkLogic 服务器中复制整个项目文件夹,而不是手动执行,我决定使用递归函数来执行它,但这正在成为我曾经有过的最糟糕的想法。我在交易和语法方面遇到问题,但作为新手,我找不到真正的解决方法。这是我的代码,谢谢你的帮助!
import module namespace dls = "http://marklogic.com/xdmp/dls" at "/MarkLogic/dls.xqy";
declare option xdmp:set-transaction-mode "update";
declare function local:recursive-copy($filesystem as xs:string, $uri as xs:string)
{
for $e in xdmp:filesystem-directory($filesystem)/dir:entry
return
if($e/dir:type/text() = "file")
then dls:document-insert-and-manage($e/dir:filename, fn:false(), $e/dir:pathname)
else
(
xdmp:directory-create(concat(concat($uri, data($e/dir:filename)), "/")),
local:recursive-copy($e/dir:pathname, $uri)
)
};
let $filesystemfolder := 'C:\Users\WB523152\Downloads\expath-ml-console-0.4.0\src'
let $uri := "/expath_console/"
return local:recursive-copy($filesystemfolder, $uri)
MLCP 会很好用。但是,这是我的版本:
declare option xdmp:set-transaction-mode "update";
declare variable $prefix-replace := ('C:/', '/expath_console/');
declare function local:recursive-copy($filesystem as xs:string){
for $e in xdmp:filesystem-directory($filesystem)/dir:entry
return
if($e/dir:type/text() = "file")
then
let $source := $e/dir:pathname/text()
let $dest := fn:replace($source, $prefix-replace[1], $prefix-replace[2])
let $_ := xdmp:document-insert($source,
<options xmlns="xdmp:document-load">
<uri>{$dest}</uri>
</options>)
return <record>
<from>{$source}</from>
<to>{$dest}</to>
</record>
else
local:recursive-copy($e/dir:pathname)
};
let $filesystemfolder := 'C:\Temp'
return <results>{local:recursive-copy($filesystemfolder)}</results>
请注意以下事项:
- 我将示例更改为 C:\Temp 目录
- 输出是 XML 只是因为按照惯例我尝试这样做以防我想分析结果。这实际上是我发现与更新冲突相关的错误的方式。
- 我选择在 URI 上定义一个简单的前缀替换
- 根据您的描述,我认为不需要 DLS
- 我认为在您的用例中不需要显式创建目录
- 您收到冲突更新的原因是您仅使用文件名作为 URI。在整个目录结构中,这些名称不是唯一的 - 因此对相同 URI 的双重插入进行冲突更新。
- 这不是可靠的代码:
- 您必须确保 URI 有效。并非所有文件系统 paths/names 都适用于 URI,因此您需要对此进行测试并在需要时转义字符。
- 大型文件系统会超时,因此分批生成可能很有用。
- 举个例子,我可能会像 XML 中那样收集文档列表,然后通过为每 100 个文档生成一个新任务来处理该列表。这可以通过 xdmp:spawn 函数上的简单循环或使用 @mblakele 的 taskbot 等库来完成