简体   繁体   English

使用XQuery递归复制文件夹

[英]Recursive copy of a folder with XQuery

I have to copy an entire project folder inside the MarkLogic server and instead of doing it manually I decided to do it with a recursive function, but is becoming the worst idea I have ever had. 我必须在MarkLogic服务器内部复制整个项目文件夹,而不是手动执行,我决定使用递归函数来完成它,但这是我有史以来最糟糕的想法。 I'm having problems with the transactions and with the syntax but being new I don't find a true way to solve it. 我遇到了事务和语法方面的问题,但是我没有找到解决问题的真正方法。 Here's my code, thank you for the help! 这是我的代码,谢谢你的帮助!

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 would have been nice to use. MLCP本来很好用。 However, here is my version: 但是,这是我的版本:

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> 

Please note the following: 请注意以下事项:

  • I changed my sample to the C:\\Temp dir 我将我的样本更改为C:\\ Temp目录
  • The output is XML only because by convention I try to do this in case I want to analyze results. 输出只是XML,因为按照惯例,我尝试这样做,以防我想分析结果。 It is actually how I found the error related to conflicting updates. 实际上,我发现了与冲突更新相关的错误。
  • I chose to define a simple prefix replace on the URIs 我选择在URI上定义一个简单的前缀替换
  • I saw no need for DLS in your description 我在你的描述中看不到DLS
  • I saw no need for the explicit creation of directories in your use case 我认为不需要在用例中显式创建目录
  • The reason you were getting conflicting updates because you were using just the filename as the URI. 您之所以获得冲突的原因是因为您只使用文件名作为URI。 Across the whole directory structure, these names were not unique - hence the conflicting update on double inserts of same URI. 在整个目录结构中,这些名称不是唯一的 - 因此对同一URI的双重插入进行冲突更新。
  • This is not solid code: 这不是可靠的代码:
    • You would have to ensure that a URI is valid. 您必须确保URI有效。 Not all filesystem paths/names are OK for a URI, so you would want to test for this and escape chars if needed. 并非所有文件系统路径/名称都适用于URI,因此您需要测试此内容并在需要时转义字符。
    • Large filesystems would time-out, so spawning in batches may be useful. 大型文件系统会超时,因此批量生成可能会有用。
      • A an example, I might gather the list of docs as in my XML and then process that list by spawning a new task for every 100 documents. 举个例子,我可能会收集我的XML中的文档列表,然后通过为每100个文档生成一个新任务来处理该列表。 This could be accomplished by a simple loop over xdmp:spawn-function or using a library such as taskbot by @mblakele 这可以通过xdmp:spawn-function上的简单循环或@mblakele使用诸如taskbot之类的库来实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM