2016-03-01 15 views
8

“invalid values” setting on an element range index'u kullanan bir kodum var. Bu durumda, veritabanımda onDate öğesinde bir dateTime öğe aralığı dizini yapılandırdım (bu hem XML öğeleri hem de JSON özellikleri için geçerlidir). Bu endeksi geçersiz değerleri reddetmek üzere ayarlıyorum. Bu ayar, bir onDate öğesinin değerini ayarlamaya çalıştığımda ve dateTime için sabitlenemiyorsa veya null (JSON'da null veya XML'de xsi:nil="true") değilse, güncelleştirmem başarısız olur. (Zıt davranış tamamen geçersiz değerler göz ardı etmektir.) Neden bir MarkLogic isteğindeki belirli istisnaları yakalayamıyorum?

Ben MarkLogic 8,0-4 yılında Sunucu Tarafı JavaScript aşağıdaki kodu çalıştı:

benim isteği başarılı olmak ve sona ermesi bekleniyor olurdu

'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; 
1 === errors.length ile yukarı, çünkü 'asdf' dateTime olarak yalnızca ikinci ekleme başarısız olabilir ve boş değil. Ancak, bunun yerine bir XDMP-RANGEINDEX hatası alıyorum ve işlem başarısız oluyor. Neden benim try/ catch burada çalışmıyor?

cevap

13

Sorun, MarkLogic işlemlerinin işlemleri nasıl güncelleştirdiğidir. Her bir xdmp.docuentInsert(…) numaralı çağrıyla verileri değiştirmekten ziyade, MarkLogic tüm güncellemeleri sıraya alır ve isteklerin sonunda atomik olarak uygular. (Bu aynı zamanda veritabanı güncellemelerini aynı işlem içerisinde görememeniz de mümkündür.) Bu nedenle, hata yürütüldükten ve veritabanı, sıraya alınmış işlemleri gerçekleştirmeye çalışıncaya kadar hata atılmaz. Bu davranış (hafifçe basitleştirilmiş) XQuery aynıdır: eşzamanlı hataları yakalamak için

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) 
    } 

, sen kendi tür bir işlemi her güncelleştirme koymak gerekiyordu. Genel olarak, bu yaklaşım MarkLogic’in varsayılan işlem işlemciliğinden çok daha yavaş ve kaynak yoğun olacaktır. Ancak, kapaklar altında neler olup bittiğini ortaya koymak ve bunun gibi belirli kullanım durumları için kullanışlı olabilmeleri burada açıklayıcıdır. Aşağıdaki örnekte, ebeveyn isteğinden ayrı bir işlemde "çağrı" yapmak için kullanıyorum. (Kazanmak için birinci sınıf işlevler!) Bu, güncellemelerin (veya hataların) görülebilmesi için güncellemelerin tam olarak uygulanmasına (veya bir hatayla geri alınmasına) ve arama modülüne izin verir. Alt düzey xdmp.invokeFunction()'u, applyAs() işlevimde, işlev argümanlarını doğru bir şekilde işlev gören işlevlere yönlendirmek gibi bazı ayrıntıları sağlamak için kullandım.

'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

Artık cevabı kabul etmek gerek;) ben oy sahtekarlığı önlemek için hayal – joemfb

+0

, iki gün boyunca kendi cevap kabul edemeyiz. –