2016-03-01 29 views
8

Tôi có một số mã thực hiện “invalid values” setting on an element range index. Trong trường hợp này, tôi đã định cấu hình chỉ mục phạm vi phần tử dateTime trên phần tử onDate trong cơ sở dữ liệu của tôi (sẽ áp dụng cho cả phần tử XML và thuộc tính JSON). Tôi đã đặt chỉ mục đó để từ chối các giá trị không hợp lệ. Cài đặt này có nghĩa là nếu tôi cố gắng đặt giá trị của một phần tử onDate và không thể đặt thành dateTime hoặc không có giá trị (null bằng JSON hoặc xsi:nil="true" trong XML), bản cập nhật của tôi sẽ không thành công. (Các hành vi ngược lại là hoàn toàn bỏ qua các giá trị không hợp lệ.)Tại sao tôi không thể nhận một số ngoại lệ nhất định trong yêu cầu MarkLogic?

Tôi đã thử các mã sau vào Server-Side JavaScript trong MarkLogic 8,0-4:

'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; 

tôi dự kiến ​​sẽ có yêu cầu của tôi để thành công và kết thúc lên với 1 === errors.length, bởi vì chỉ chèn thứ hai sẽ không thành công vì 'asdf' không thể bỏ qua dưới dạng dateTime và nó không phải là rỗng. Tuy nhiên, thay vào đó tôi nhận được lỗi XDMP-RANGEINDEX và giao dịch của tôi không thành công. Tại sao không try/catch hoạt động ở đây?

Trả lời

13

Vấn đề là cách MarkLogic xử lý các giao dịch cập nhật. Thay vì thực sự thay đổi dữ liệu với mỗi cuộc gọi xdmp.docuentInsert(…), MarkLogic xếp hàng tất cả các bản cập nhật và áp dụng chúng một cách nguyên tử vào cuối yêu cầu. (Đây cũng là lý do tại sao bạn không thể nhìn thấy các cập nhật cơ sở dữ liệu trong cùng một giao dịch.) Vì vậy, lỗi không được ném cho đến sau khi vòng lặp đã được thực hiện và cơ sở dữ liệu cố gắng thực hiện các giao dịch được xếp hàng đợi. Hành vi này giống nhau trong XQuery (hơi đơn giản hóa):

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

Để nắm bắt các lỗi đồng bộ, bạn cần đặt từng cập nhật vào giao dịch của chính nó. Nói chung, cách tiếp cận này sẽ chậm hơn và tốn nhiều tài nguyên hơn so với xử lý giao dịch mặc định của MarkLogic. Tuy nhiên, nó minh họa ở đây để chứng minh những gì đang xảy ra dưới sự che chở và có thể có ích cho các trường hợp sử dụng cụ thể, như trường hợp này.

Trong ví dụ bên dưới, tôi sử dụng xdmp.invokeFunction() để “gọi” một hàm trong một giao dịch riêng biệt từ yêu cầu gốc. (Các chức năng hạng nhất để giành chiến thắng!) Điều này cho phép các bản cập nhật được áp dụng đầy đủ (hoặc quay lại với lỗi) và mô-đun gọi để xem các bản cập nhật (hoặc lỗi). Tôi đã bao bọc các mức độ thấp xdmp.invokeFunction() trong chức năng applyAs() của riêng mình để cung cấp một số tính năng chính xác, chẳng hạn như chuyển các đối số hàm chính xác sang chức năng được thu thập.

'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

Bây giờ bạn cần chấp nhận câu trả lời của bạn;) – joemfb

+0

Tôi tưởng tượng để tránh nhồi lá phiếu, bạn không thể chấp nhận câu trả lời của riêng bạn trong hai ngày. –

Các vấn đề liên quan