2017-08-29 4 views
1

MarkLogicサーバー内のプロジェクトフォルダ全体をコピーしなければならず、手動で行う代わりに、再帰関数を使用することにしましたが、これまでになかった最悪の考えになりつつあります。私はトランザクションと構文に問題がありますが、新しいものでは解決する真の方法は見つけられません。ここで私のコードは、助けてくれてありがとう!XQueryを使用したフォルダの再帰的コピー

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) 
+0

によってあなたはどのように多くの文書をコピーしていますか?データセットが非常に大きい場合、優れたソリューションが狭くなります。また、あなたはdlsが必要ですか? good-ol xdmp:document-insertを使ってもいいですか? –

+0

@ SamMeffordまあ、私はUIコンソールとして機能するネストされたプロジェクト全体をコピーしようとしています。そのため、xdmp:document-insertだけを使用すると、サーバー自体の中のファイルとフォルダの階層を見ることができません。いいえ、私はdlsについてはわかりません、私はちょうど解決策を見つけようとしています。また、mlcpコマンドを使用しようとしましたが、サーバーに到達できません。 – MissArmstrong

答えて

3

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は、慣例により、私がしようという理由だけで結果を分析したい場合に備えてください。これは、実際に、競合する更新プログラムに関連するエラーをどのように検出したかです。
  • 私はあなたのユースケース
  • にあなたがいた理由を、ディレクトリを明示的に作成するための必要性を全く見ていない私は
  • あなたの説明にDLSの必要性を見ていないシンプルな接頭辞はURIの
  • に置き換える定義することにしましたファイル名だけをURIとして使用していたため、更新が競合していました。ディレクトリ構造全体にわたって、これらの名前はユニークではありませんでした - したがって、同じURIの二重の挿入に関する競合する更新。
  • これは、固体のコードではありません:あなたはURIが有効であることを確認しなければならないでしょう
    • 。すべてのファイルシステムのパス/名前がURIでOKなわけではありませんので、必要に応じてこの文字とエスケープ文字をテストしたいと考えています。
    • 大きなファイルシステムはタイムアウトするため、バッチでの産卵が役立つ場合があります。
      • たとえば、ドキュメントのリストを自分のXMLと同じように収集し、100個のドキュメントごとに新しいタスクを作成してそのリストを処理することができます。これはxdmp上で単純なループによって達成することができる:産卵機能や、taskbotなどのライブラリを使用して@mblakele
+0

私はコードが最高の品質ではないことを認識しています。私はその限界を理解していますが、プロジェクトはかなり小さいので、私は大きなファイルシステムを考えませんでした。反対側では、プロジェクトは手作業でコピーするほど小さくないので、コピーを自動化しようとしました。私もmlcpで試してみましたが、現在、特定のデータベースにファイルをコピーすると言うと問題を抱えています。私が見つけた唯一の解決策は、App-Servicesのデフォルトサーバーから参照されるデータベースを変更することです。私はそれがかなり残酷なアプローチだと知っていますが、私はこれらのことに新しいので、私はどのように問題に直面しています。 – MissArmstrong

+0

とにかく、あなたの解決に感謝します、私はすぐにそれを試してみましょう! – MissArmstrong

+0

mlcpはポート8000​​に対して実行でき、-output_databaseオプションがあります。セクション2.4:https://docs.marklogic.com/guide/mlcpを参照してください。pdf –

関連する問題