2016-08-17 54 views
1

爲了測試使用觸發器內DocumentDB,我:調試DocumentDB觸發

  • 上傳樣本metadata後觸發
  • 創建元數據文件與執行的某些文件屬性"isMetadata": true
  • 用C#寫包括一個RequestOption與PostTriggerInclude = new List<string> { "updateMetadata" }

不幸的是,元數據文件坐在那裏與0的blissfull當我的代碼插入文檔時,y不受觸發器的影響。我在觸發器中驗證了選擇SQL,以確保它能夠找到要編輯的元數據文檔。似乎沒有我可以用來進一步調查的日誌。

如何調試DocumentDB觸發器?

(和問題可能是郊遊,有什麼明顯的錯誤與我的設置?)

updateMetaData script

元數據文檔:

{ 
    "id": "metadata", 
    "isMetadata": true, 
    "minSize": 0, 
    "maxSize": 0, 
    "totalSize": 0, 
    } 

代碼片段:

var docResp = await client.CreateDocumentAsync(collectionUri, webhit, 
        new RequestOptions 
        { 
          PostTriggerInclude = new List<string> { "updateMetadata" } 
        } 
       ); 

回答

1

在存儲過程或觸發器中,所有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

+0

我使用了這個修訂版本,唱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' –

+0

嗨Steph,你是怎麼「讀」這個集合的?從門戶或我的C#代碼中讀取數據和元數據文檔都沒有問題。您所做的特定操作從我們身邊產生了一個錯誤,表示觸發器的操作類型無效。當你的行爲不是創建,刪除或替換時,你似乎試圖調用觸發器。你能讓我知道更多有關你的「閱讀」操作的信息嗎?謝謝。 –