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;
}
}
}
Bây giờ bạn cần chấp nhận câu trả lời của bạn;) – joemfb
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. –