2016-06-10 48 views
0

我有一個測試案例在這裏:xdmp:評估和更新交易

let $s := 
'xquery version "1.0-ml"; 
for $doc in xdmp:directory("/test/") 
       return 
       xdmp:node-insert-child(doc(xdmp:node-uri($doc))/a, 
    <b>bbb</b>) 
return 
(xdmp:eval($s,(), <options xmlns="xdmp:eval"> 
     <isolation>different-transaction</isolation> 
     <prevent-deadlocks>true</prevent-deadlocks> 
    </options>), xdmp:directory("/test/")) 

我在這裏的主要目標是到一個新的元素在同一事務添加到每個文件「/測試/」並返回結果。與xdmp:eval()和「不同交易」選項我認爲評估代碼將在一個單獨的交易中執行,其更新將可用於後續調用...所以第二個也是最後一個xdmp:directory("/test/")應該返回所有更新的文檔與<b>元素,但它返回未更新的文檔。

在這裏有任何注意事項xdmp:eval和我試圖在單個交易中實現什麼?

+0

也許懶惰的評價?您可以通過將eval的結果賦值給一個變量,然後強制評估該變量('let $ _eval:= xdmp:eval(...)let $ test:= empty($ _ eval)''來測試。更好的解決方案可能是使用XSLT或遞歸類型轉換在內存中轉換文檔,將其插入到原始文檔上並返回它還有一個ML內存更新庫,可以簡化某些語法,可以簡化一些語法 – wst

+0

@謝謝,將嘗試強制評估,還有XSLT和類型切換,因爲這是操縱JSON(您昨天回答的問題),我轉換爲XML示例以使測試用例更簡單。 – Laterade

回答

3

Marklogic 8在這種情況下,我的想法是,我從主腳本調用的函數中進行更新。我使用的設置不僅提交文檔,而且還將新提交公開給初始代碼。由於MarkLogic如何處理代碼中的時間戳,僅僅因爲可能會提交某些內容並不意味着它可用於代碼。爲什麼?因爲提交的時間戳是在代碼開始運行之後(或類似的)。這種方法解決了這個問題。另外,我選擇了MarkLogic 8的例子,因爲原來的問題沒有將其範圍擴大到以前的版本。所以我使用了當前版本MarkLogic的解決方案。

xquery version "1.0-ml"; 

(: load docs 
for $foo in (1 to 5) 
    let $uri := "/test/child/foo" || xs:string($foo) || ".xml" 
    return xdmp:document-insert($uri, <foo><bar></bar></foo>) 
:) 

let $update := xdmp:invoke-function(function(){ 
    (for $uri in cts:uri-match("/test/child/foo*") 
     return xdmp:node-insert-child(doc($uri)/foo/bar, <baz>bbb</baz>) 
    ,xdmp:commit() 
    ) 
    }, 
    <options xmlns="xdmp:eval"> 
     <transaction-mode>update-auto-commit</transaction-mode> 
     <isolation>different-transaction</isolation> 
    </options> 
) 

return xdmp:directory("/test/child/")