2016-03-01 7 views
8

私は“invalid values” setting on an element range indexを実行するいくつかのコードを持っています。この場合、データベース内のonDate要素(XML要素とJSONプロパティの両方に適用されます)に要素範囲インデックスdateTimeを設定しました。無効な値を拒否するようにそのインデックスを設定しました。この設定は、onDate要素の値を設定しようとしたときに、dateTimeにキャストできないか、null(JSONの場合はnull、XMLの場合はxsi:nil="true")であれば、更新が失敗します。 (逆の動作が完全に無効な値を無視することである。)MarkLogicリクエストで特定の例外を検出できないのはなぜですか?

私はMarkLogic 8.0から4でサーバサイドJavaScriptに次のコードを試してみました:

'use strict'; 
declareUpdate(); 
var errors = []; 
var inputs = { 
'/37107-valid.json': (new Date()).toISOString(), 
'/37107-invalid.json': 'asdf', // Should throw an error 
'/37107-null.json': null 
}; 

for(var uri in inputs) { 
try { 
    xdmp.documentInsert(
    uri, 
    { 'onDate': inputs[uri] }, 
    xdmp.defaultPermissions(), 
    ['37107'] // Collections 
    ); 
} catch(err) { 
    errors.push(err); 
} 
} 
errors.length; 

私が成功すると最後に私の要求を期待しているだろう'asdf'はキャスト可能ではなくdateTimeであり、nullではないため、2番目のインサートのみが失敗したため、1 === errors.lengthを使用してアップします。ただし、代わりにXDMP-RANGEINDEXエラーが発生し、トランザクションが失敗します。 try/catchはなぜここで動作しませんか?

答えて

13

問題はMarkLogicが更新トランザクションを処理する方法です。各xdmp.docuentInsert(…)コールで実際にデータを変更するのではなく、MarkLogicはすべての更新をキューに入れ、要求の最後にアトミックに適用します。これは、同じトランザクション内でデータベースの更新を見ることができない理由です。したがって、ループが実行され、データベースがキューに入れられたトランザクションをコミットしようとするまで、エラーはスローされません。この動作は、XQuery(やや簡略化)に同じです。

let $uris := (
'/37107-valid.xml', 
'/37107-invalid.xml', 
'/37107-null.xml' 
) 
let $docs := (
<onDate>{fn:current-dateTime()}</onDate>, 
<onDate>asdf</onDate>, 
<onDate xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/> 
) 
return 
for $uri at $i in $uris 
return 
    try { 
    xdmp:document-insert($uri, $docs[$i],(), ('37107')) 
    } catch($err) { 
    xdmp:log($err) 
    } 

同期エラーをキャッチするためには、あなたが独自のトランザクションに各更新を配置する必要があると思います。一般に、このアプローチは、MarkLogicのデフォルトのトランザクション処理よりもはるかに遅く、リソースを集中します。ただし、ここでは何が起こっているかを実証するための説明があり、このような特定のユースケースには便利です。

以下の例では、私はxdmp.invokeFunction()を使用して、親要求とは別のトランザクションで関数を "呼び出し"ます。 (優勝のためのファーストクラスの機能!)これにより、アップデートが完全に適用される(またはエラーでロールバックされる)ことと、呼び出しモジュールが更新(またはエラー)を見ることができます。私は自分のapplyAs()関数で低レベルのxdmp.invokeFunction()をラップしました。関数の引数をカルトした関数に正しく渡すような細かさを提供しています。

'use strict'; 

var errors = []; 
var inputs = { 
'/37107-valid.json': (new Date()).toISOString(), 
'/37107-invalid.json': 'asdf', 
'/37107-null.json': null 
}; 

var insert = applyAs(
function(uri, value) { 
    return xdmp.documentInsert(
    uri, 
    { 'onDate': inputs[uri] }, 
    xdmp.defaultPermissions(), 
    ['37107'] 
    ); 
}, 
{ isolation: 'different-transaction', transactionMode: 'update' }, 
'one' 
); 

for(var uri in inputs) { 
try { 
    insert(uri, inputs[uri]); 
} catch(err) { 
    errors.push(err); 
} 
} 
errors.length; // Correctly returns 1 


// <https://gist.github.com/jmakeig/0a331823ad9a458167f6> 
function applyAs(fct, options, returnType /* 'many', 'one', 'iterable' (default) */) { 
    options = options || {}; 
    return function() { 
    var params = Array.prototype.slice.call(arguments); 
    // Curry the function to include the params by closure. 
    // xdmp.invokeFunction requires that invoked functions have 
    // an arity of zero. 
    var f = (function() { 
     return fct.apply(null, params); 
    }).bind(this); 
    // Allow passing in user name, rather than id 
    if(options.user) { options.userId = xdmp.user(options.user); delete options.user; } 
    // Allow the functions themselves to declare their transaction mode 
    if(fct.transactionMode && !(options.transactionMode)) { options.transactionMode = fct.transactionMode; } 
    var result = xdmp.invokeFunction(f, options); // xdmp.invokeFunction returns a ValueIterator 
    switch(returnType) { 
     case 'one': 
     // return fn.head(result); // 8.0-5 
     return result.next().value; 
     case 'many': 
     return result.toArray(); 
     case 'iterable': 
     default: 
     return result; 
    } 
    } 
} 
+0

今、あなたはあなたの答えを受け入れる必要があります;)私は投票詰め物を避けるために想像 – joemfb

+0

、あなたは2日間、あなた自身の答えを受け入れることはできません。 –

関連する問題