Recursion 使用XQuery递归复制文件夹

Recursion 使用XQuery递归复制文件夹,recursion,transactions,xquery,marklogic,xquery-update,Recursion,Transactions,Xquery,Marklogic,Xquery Update,我必须在MarkLogic服务器中复制整个项目文件夹,我决定用递归函数来代替手动操作,但这已经成为我有过的最糟糕的想法。我在事务和语法方面有问题,但作为新手,我并没有找到真正的解决方法。这是我的代码,谢谢你的帮助 import module namespace dls = "http://marklogic.com/xdmp/dls" at "/MarkLogic/dls.xqy"; declare option xdmp:set-transaction-mode "update"; dec

我必须在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> 
声明选项xdmp:设置事务模式“更新”;
声明变量$prefix replace:=('C:/','/expath_console/');
声明函数local:recursive copy($filesystem as xs:string){
xdmp:filesystem目录($filesystem)/dir:entry中的$e
返回
if($e/dir:type/text()=“文件”)
然后
让$source:=$e/dir:pathname/text()
让$dest:=fn:replace($source,$prefix replace[1],$prefix replace[2])
让$xdmp:document插入($source,
{$dest}
)
返回
{$source}
{$dest}
其他的
本地:递归副本($e/dir:pathname)
};
让$filesystemfolder:=“C:\Temp”
返回{local:recursive copy($filesystemfolder)}
请注意以下事项:

  • 我将示例更改为C:\Temp dir
  • 输出是XML,只是因为按照惯例,我会在需要分析结果时尝试这样做。这实际上是我发现与冲突更新相关的错误的方式
  • 我选择在URI上定义一个简单的前缀替换
  • 我在你的描述中看不到需要DLS
  • 我认为没有必要在您的用例中显式创建目录
  • 您仅使用文件名作为URI而获得冲突更新的原因。在整个目录结构中,这些名称不是唯一的——因此在相同URI的两个插入上的更新冲突
  • 这不是可靠的代码:
    • 您必须确保URI是有效的。并不是所有文件系统路径/名称都适合URI,所以您需要对此进行测试,并在需要时转义字符
    • 大型文件系统可能会超时,因此批量生成可能很有用。
      • 例如,我可能会收集XML中的文档列表,然后通过为每100个文档生成一个新任务来处理该列表。这可以通过一个简单的xdmp:spawn函数上的循环或使用@mblakele之类的库来实现

您要复制多少文档?如果您的数据集非常大,那么好的解决方案会缩小范围。另外,您确定需要dls吗?好的ol-xdmp:document-insert是否可以?@SamMefford我正试图复制一个作为UI控制台的整个嵌套项目,以查看服务器本身中文件和文件夹的层次结构,因此,不,仅使用xdmp:document-insert不会有帮助。不,我不确定dls,我只是想找到一个解决方案。我也尝试过使用mlcp命令,但它无法到达服务器。我知道代码的质量不是最好的,我理解它的局限性,但由于项目非常小,我没有想到大型文件系统。另一方面,该项目不是那么小,无法手动复制,因此这是一次尝试自动化复制。我也尝试使用mlcp,但目前我无法告诉他文件复制到哪个特定数据库,我找到的唯一解决方案是更改默认服务器App Services引用的数据库。我知道这是一个相当残酷的方法,但作为一个新手,我正在努力面对我能面对的问题。无论如何,谢谢你的解决方案,我会很快尝试的!mlcp可以在端口8000上运行,并具有-output_数据库选项。请参阅此处的第2.4节:从网站上的marklogic指南可以选择针对特定端口运行命令,但它是伪装的,因此我只能在端口8000上运行它,但感谢您提供了另一个选项,这似乎是解决我发现的问题的合理方法!