在存儲過程或觸發器中,所有Error tha腳本拋出將被傳回並翻譯成客戶端異常,並帶有堆棧跟蹤。因此,調試腳本的一種方法是在腳本中使用throw new Error(...)作爲斷點,逐步執行腳本並投擲不同的點以驗證代碼的行爲是否符合預期。
假設您正在使用分區集合。觸發器,就像存儲過程一樣,被限制在一個分區中(https://azure.microsoft.com/en-us/documentation/articles/documentdb-programming/#database-program-transactions)。因此,觸發器可以訪問和更新的內容必須位於觸發器正在運行的分區內。
在您的示例中,如果不更改觸發器腳本,則需要爲每個分區鍵值預先創建一個元數據文檔。然後,要獲得收集的最終統計信息,您需要查詢所有元數據文檔(將會有多個),並在客戶端對這些元數據文檔進行最終聚合。
另一種選擇是自動創建觸發器內的元數據文檔。這將避免創建超過必要的元數據文檔,因爲每個分區只需要一個元數據文檔。這是我的原始腳本的修改,創建:
/**
* This script runs as a trigger:
* for each inserted document, look at document.size and update aggregate properties of metadata document: minSize, maxSize, totalSize.
*/
function updateMetadata() {
// HTTP error codes sent to our callback funciton by DocDB server.
var ErrorCode = {
RETRY_WITH: 449,
}
var collection = getContext().getCollection();
var collectionLink = collection.getSelfLink();
// Get the document from request (the script runs as trigger, thus the input comes in request).
var doc = getContext().getRequest().getBody();
// Check the doc (ignore docs with invalid/zero size and metaDoc itself) and call updateMetadata.
if (!doc.isMetadata && doc.size != undefined && doc.size > 0) {
getAndUpdateMetadata();
}
function getAndUpdateMetadata() {
// Get the meta document. We keep it in the same collection. it's the only doc that has .isMetadata = true.
var isAccepted = collection.queryDocuments(collectionLink, 'SELECT * FROM TestColl r WHERE r.isMetadata = true', function (err, feed, options) {
if (err) throw err;
var metaDoc;
if (!feed || !feed.length) {
// Create the meta doc for this partition, using the partition key value from the request document
metaDoc = {
"id": "metadata",
"isMetadata": true,
"minSize": 0,
"maxSize": 0,
"totalSize": 0,
}
metaDoc.partitionKey = doc.partitionKey;
}
else {
// Found the metadata document for this partition. So just use it
metaDoc = feed[0];
}
// Update metaDoc.minSize:
// for 1st document use doc.Size, for all the rest see if it's less than last min.
if (metaDoc.minSize == 0) metaDoc.minSize = doc.size;
else metaDoc.minSize = Math.min(metaDoc.minSize, doc.size);
// Update metaDoc.maxSize.
metaDoc.maxSize = Math.max(metaDoc.maxSize, doc.size);
// Update metaDoc.totalSize.
metaDoc.totalSize += doc.size;
// Update/replace the metadata document in the store.
var isAccepted;
if (!feed || !feed.length) {
// Create the metadata document if it doesn't exist
isAccepted = collection.createDocument(collectionLink, metaDoc, function (err) {
if (err) throw err;
// Note: in case concurrent updates causes conflict with ErrorCode.RETRY_WITH, we can't read the meta again
// and update again because due to Snapshot isolation we will read same exact version (we are in same transaction).
// We have to take care of that on the client side.
});
}
else {
// Replace the metadata document
isAccepted = collection.replaceDocument(metaDoc._self, metaDoc, function (err) {
if (err) throw err;
// Note: in case concurrent updates causes conflict with ErrorCode.RETRY_WITH, we can't read the meta again
// and update again because due to Snapshot isolation we will read same exact version (we are in same transaction).
// We have to take care of that on the client side.
});
}
if (!isAccepted) throw new Error("The call replaceDocument(metaDoc) returned false.");
});
if (!isAccepted) throw new Error("The call queryDocuments for metaDoc returned false.");
}
}
希望這有助於。如果您還有其他問題,請隨時回覆。
感謝。
Lengning
我使用了這個修訂版本,唱Azure DocumentDB Studio我可以添加一個文檔幷包含updataMetadata作爲PostTrigger。它增加了文檔並且返回正常,但是隨後有趣的是,如果我以後嘗試「讀取」任何東西,我會得到'Microsoft.Azure.Documents。DocumentClientException:消息:{「Errors」:[「其中一個指定的輸入無效」]} ActivityId:706529a1-82b9-4ed1-a395-6090ddf91b50,請求URI:/ apps/36834417-c2b8-4524-871e-e3247817af32 /服務/ 78da0810-31a5-45d3-bb94-8ef7a68e12cd/partitions/91e5e314-dc36-419e-84d8-fba2825499c9/replicas/131157324155592025s' –
嗨Steph,你是怎麼「讀」這個集合的?從門戶或我的C#代碼中讀取數據和元數據文檔都沒有問題。您所做的特定操作從我們身邊產生了一個錯誤,表示觸發器的操作類型無效。當你的行爲不是創建,刪除或替換時,你似乎試圖調用觸發器。你能讓我知道更多有關你的「閱讀」操作的信息嗎?謝謝。 –