J'ai écrit une procédure stockée af pour ajouter une propriété Type à tous les documents d'une collection DocumentDB. Malheureusement, la procédure stockée échoue après la mise à jour d'un seul document. La collection contient environ 5000 documents.Echec de la mise à jour de plusieurs documents DocumentDB
Voici la procédure stockée:
function updateSproc() {
var collection = getContext().getCollection();
var collectionLink = collection.getSelfLink();
var response = getContext().getResponse();
var responseBody = {
updated: 0,
continuation: true,
error: "",
log: ""
};
// Validate input.
tryQueryAndUpdate();
// Recursively queries for a document by id w/ support for continuation tokens.
// Calls tryUpdate(document) as soon as the query returns a document.
function tryQueryAndUpdate(continuation) {
var query = { query: "SELECT * FROM root c WHERE NOT is_defined(c.Type)", parameters: []};
var requestOptions = { continuation: continuation};
var isAccepted = collection.queryDocuments(collectionLink, query, requestOptions, function(err, documents, responseOptions) {
if (err) {
responseBody.error = err;
throw err;
}
if (documents.length > 0) {
// If documents are found, update them.
responseBody.log += "Found documents: " + documents.length;
tryUpdate(documents);
} else if (responseOptions.continuation) {
responseBody.log += "Continue query";
tryQueryAndUpdate(responseOptions.continuation);
} else {
responseBody.log += "No more documents";
responseBody.continuation = false;
response.setBody(responseBody);
}
});
// If we hit execution bounds - throw an exception.
if (!isAccepted) {
responseBody.log += "Query not accepted";
response.setBody(responseBody);
}
}
// Updates the supplied document according to the update object passed in to the sproc.
function tryUpdate(documents)
{
if (documents.length > 0) {
responseBody.log += "Updating documents " + documents.length;
var document = documents[0];
// DocumentDB supports optimistic concurrency control via HTTP ETag.
var requestOptions = { etag: document._etag};
document.Type="Type value";
// Update the document.
var isAccepted = collection.replaceDocument(document._self, document, requestOptions, function(err, updatedDocument, responseOptions) {
if (err) {
responseBody.error = err;
throw err;
}
responseBody.updated++;
documents.shift();
tryUpdate(documents);
});
// If we hit execution bounds - throw an exception.
if (!isAccepted) {
responseBody.log += "Update not accepted";
response.setBody(responseBody);
}
} else {
tryQueryAndUpdate();
}
}}
Sur la base de la réponse fournie, je peux voir que la requête renvoie 100 documents. tryUpdate est appelée deux fois mais le second appel à replaceDocument n'est pas accepté. Pourquoi n'est-il pas accepté lorsqu'il y a beaucoup de documents à mettre à jour?
J'ai passé environ 20 minutes à regarder cela et je ne vois rien d'évident. La seule chose mineure que j'ai vue ne causerait pas votre problème. Vous appelez tryUpdate() même si isAccepted est false, ce qui signifie que vous pouvez essayer d'appeler replaceDocument() après que DocumentDB vous ait dit qu'il n'accepte plus les opérations. La seule autre chose que je pourrais essayer serait de mettre des documents dans la portée de fonction de niveau supérieur, puis changer votre callback sur la requête pour dire 'results' au lieu de' documents' et ajouter 'documents = results' juste après votre erreur vérifier. –
Ohh, il semblerait que votre code ne verra jamais le bloc qui appelle tryQueryAndUpdate avec une continuation, mais cela signifierait que vous ne pourriez pas obtenir une seconde page, cela n'entraînerait pas l'échec de votre deuxième appel replaceDocuments().Je vais nouilles dessus encore un peu et peut-être essayer de vivre moi-même. –
Ohh, si vous déplacez des documents dans la portée de niveau supérieur, n'oubliez pas de ne pas passer les documents dans tryUpdate. –