練習 - 使用輸出繫結寫入資料

已完成

在上一個練習中,我們實作了在 Azure Cosmos DB 資料庫中查詢書籤的案例。 我們設定了從書籤集合讀取資料的輸入繫結。 但是,我們可做的不只這些。 請展開案例以包含撰寫內容。 請考量下列流程圖:

此決策流程圖說明在 Azure Cosmos DB 後端新增書籤並傳回回應的流程。

在此案例中,我們收到將書籤新增至集合的要求。 此要求會傳入所需的索引鍵或識別碼,以及書籤 URL。 如您在流程圖中所見,如果該索引鍵已存在於後端,將以錯誤來回應。

如果找不到傳遞給我們的索引鍵,即會將新書籤新增到我們的資料庫。 我們可以到此為止,但讓我們再多進行一些動作。

注意到流程圖中的另一個步驟嗎? 到目前為止,我們未對收到的資料進行太多處理。 我們會將收到的內容移入資料庫。 不過,在實際解決方案中,我們可能會透過某種方式來處理資料。 我們可以透過相同的函式來進行所有處理,但在此練習中,我們所示範的模式會將進一步處理卸載到另一個元件或部分商務邏輯。

在我們的書籤案例中,有一個卸載工作的良好範例是什麼? 如果我們將新的書籤傳送至 QR 代碼產生服務,會發生什麼情況? 該服務接著會產生 URL 的 QR 代碼、將影像儲存在 Blob 儲存體中,並將 QR 影像位址新增到書籤集合的項目中。 呼叫服務以產生 QR 影像相當耗時。 因此,與其等候結果,我們會將此工作交給函式,讓它以非同步方式完成此工作。

如同 Azure Functions 支援各種整合來源的輸入繫結,它也有一組適用於輸出繫結的範本,可讓您輕鬆地將資料寫入到資料來源。 輸出繫結也會設定於 function.json 檔案中。 如您在此練習中所見,我們可以設定函式來使用多個資料來源和服務。

重要

此練習建置於沙箱資源和您在先前單元中建立的資源之上;具體而言,即 Azure Cosmos DB 資料庫、書籤和輸入繫結。 如果您尚未完成先前單元中的練習,將無法完成此練習。

建立 HTTP 觸發函式

  1. Azure 入口網站中,移至藉由您在 HttpTrigger2 函式頁面頂端的階層連結路徑中選取函數應用程式的名稱所建立的函數應用程式。

  2. 在 [概觀] 頁面的 [函式] 索引標籤中,您應該會建立 HTTP 觸發程式函式。

  3. 選取 [函式] 索引標籤上的 [建立]。[建立函式] 窗格隨即出現。

  4. 在 [選取範本] 區段底下,選取 [HTTP 觸發程序],然後選取 [下一步]。 接受 [範本詳細資料] 索引標籤上的預設值,然後選取 [建立]HttpTrigger3 函式的 [概觀] 窗格隨即出現。

新增 Azure Cosmos DB 輸入繫結

讓我們新增另一個 Azure Cosmos DB 輸入繫結。

  1. HttpTrigger3 函式功能表中,選取 [整合]。 [整合] 窗格隨即顯示。

  2. 請在 [觸發程序和輸入] 方塊中,選取 [新增輸入]。 [建立輸入] 窗格隨即出現。

  3. 在 [繫結類型] 下拉式清單中,選取 [Azure Cosmos DB]

  4. [Cosmos DB 帳戶連線] 設定應該會預先填入您在上一個練習中所建立的連線。

    如果未列出您的連線,請遵循這些步驟來建立新連線。

    1. 在 [Azure Cosmos DB 詳細資料] 區段中,於 [Cosmos DB 帳戶連線] 設定下選取 [新增] 連結。

    2. 當 [新增 Cosmos DB 連線] 對話方塊顯示時,選取 [確定] 以建立連線。 隨即會建立新的 Cosmos DB 帳戶連線。

  5. 針對此窗格中的其他設定,輸入下列值。 在任何時候,若要深入了解某個設定的用途,您可以選取其右邊的資訊圖示。

    設定 Description
    文件參數名稱 bookmark 用來識別程式碼中此繫結的名稱。
    資料庫名稱 func-io-learn-db 要使用的資料庫。 此值是我們稍早在此課程中設定的資料庫名稱。
    集合名稱 Bookmarks 要從中讀取資料的集合名稱。 我們稍早已在此單元中定義此設定。
    文件識別碼 {id} 新增 {id} 以使用正確的繫結運算式,並接受以查詢字串傳遞的參數。
    分割區索引鍵 {id} 再次提醒,新增 {id} 以使用正確的繫結運算式,並接受以查詢字串傳遞的參數。
    SQL 查詢 (選擇性) 保留空白 我們只會根據識別碼,一次擷取一個項目。 在此情況下,使用 [文件識別碼] 設定來篩選比使用 SQL 查詢還要好。 我們可以建立 SQL 查詢以傳回一個項目 (SELECT * from b where b.ID = /id)。 該查詢確實會傳回項目,但是會在項目集合中傳回。 我們的程式碼可能會不必要地操作集合。 您想要取得多份文件時,請使用 SQL 查詢方法。

    如同我們在前一個練習中建立的輸入繫結,我們想要查閱具有特定識別碼的書籤,因此,會將函式在查詢字串中收到的文件識別碼繫結至繫結,也就是所謂的「繫結運算式」。 函式觸發程序為 HTTP 要求,會使用查詢字串指定要查閱的識別碼。 繫結會傳回 0 (找不到) 或 1 個 (找到) 文件。

  6. 選取 [新增] 以儲存此輸入繫結設定。

我們現在具備 Azure Cosmos DB 輸入繫結。 讓我們新增輸出繫結,以在集合中寫入新項目。

新增 Azure Cosmos DB 輸出繫結

  1. HttpTrigger3 的 [整合] 窗格中,於 [輸出] 方塊中,選取 [新增輸出]。 [建立輸出] 窗格隨即出現。

  2. 在 [繫結類型] 底下,從下拉式清單中,選取 [Azure Cosmos DB]

  3. [Cosmos DB 帳戶連線] 設定應該會預先填入您在先前建立的連線。 如果沒有,請展開下拉式清單,然後選取您為 HttpTrigger3 輸入繫結所定義的連線。

  4. 針對輸出繫結的其餘設定,輸入下列值。

    設定 Description
    文件參數名稱 newbookmark 用來識別程式碼中此繫結的名稱。 這個參數用來寫入新的書籤項目。
    資料庫名稱 func-io-learn-db 要使用的資料庫。 此值是我們稍早在此課程中設定的資料庫名稱。
    集合名稱 Bookmarks 要從中讀取資料的集合名稱。 此值是我們稍早在此課程中所定義的容器名稱。
    分割區索引鍵 /id 新增我們稍早在建立「書籤」Azure Cosmos DB 容器時所定義的分割區索引鍵。 在此處輸入的索引鍵 (於輸入繫結設定 <key> 中指定) 必須與容器中的索引鍵相符。
  5. 選取 [新增] 以儲存此輸出繫結設定。

現在我們有一個可從集合中讀取的繫結,以及一個要寫入到它的繫結。

新增 Azure 佇列儲存體輸出繫結

Azure 佇列儲存體是一個儲存訊息的服務,全球任何地方都可存取這些訊息。 單一訊息的大小上限為 64 KB,而一個佇列可以包含數百萬個訊息,以佇列位在其中所定義的儲存體帳戶總容量為限。 下圖會概略說明我們在案例中使用佇列的方式。

此圖顯示具有一個推送函式和另一個快顯訊息函式的儲存體佇列。

在此範例中,您看到名為 add-bookmark 的函式會將訊息新增至佇列,而另一個名為 gen-qr-code 的函式會從相同的佇列中快顯訊息,並處理要求。 由於我們將訊息從 新增書籤 寫入或 推送 到佇列,因此,會將新的輸出繫結新增到您的解決方案。

我們將透過入口網站建立繫結。

  1. 在函式的 [整合] 窗格中,於 [輸出] 方塊中,選取 [新增輸出]。 [建立輸出] 窗格隨即出現。

  2. 在 [繫結類型] 下拉式清單中,選取 [Azure 佇列儲存體]

    如果出現一則訊息提示您安裝 Microsoft.Azure.WebJobs.Extensions.Storage 延伸模組,請選取 [安裝] 並等待其完成。

接下來,我們會設定儲存體帳戶連線,其中會裝載佇列。

  1. 在 [儲存體帳戶連線] 底下,選取 [新增]。 [新增儲存體帳戶連線] 對話方塊隨即出現。

  2. 在此課程模組的開頭,當您建立函數應用程式時,也為您建立了一個儲存體帳戶。 從下拉式清單中選取它,然後選取 [確定]

    [儲存體帳戶連線] 設定會填入連線的名稱。

雖然我們可以保留預設值,但我們將變更一些設定,以便為剩餘的屬性賦予更多意義。

  1. 透過將下列舊值取代為新值,完成 [建立輸出] 窗格中的設定:

    設定 舊值 新值 描述
    訊息參數名稱 outputQueueItem newmessage 我們會在程式碼中使用的繫結屬性。
    佇列名稱 outqueue bookmarks-post-process 我們要放置書簽的佇列名稱,讓另一個函式可以進一步處理它們。
  2. 選取 [新增] 以儲存 Azure 佇列儲存體的輸出設定。

更新函式實作

我們現在已設定好所有繫結。 現在可在函式中使用這些繫結。

  1. 若要在程式碼編輯器中開啟 index.js 檔案,選取您的函式 HttpTrigger3

  2. 在功能表中,選取 [程式碼 + 測試]。 適用於您函式的 [編碼 + 測試] 窗格隨即出現。

  3. 以下列程式碼片段中的程式碼取代 index.js 檔案中的所有程式碼,然後在命令列中,選取 [儲存]

    module.exports = function (context, req) {
    
        var bookmark = context.bindings.bookmark;
        if(bookmark){
                context.res = {
                status: 422,
                body : "Bookmark already exists.",
                headers: {
                'Content-Type': 'application/json'
                }
            };
        }
        else {
            
            // Create a JSON string of our bookmark.
            var bookmarkString = JSON.stringify({ 
                id: req.body.id,
                url: req.body.url
            });
    
            // Write this bookmark to our database.
            context.bindings.newbookmark = bookmarkString;
    
            // Push this bookmark onto our queue for further processing.
            context.bindings.newmessage = bookmarkString;
    
            // Tell the user all is well.
            context.res = {
                status: 200,
                body : "bookmark added!",
                headers: {
                'Content-Type': 'application/json'
                }
            };
        }
        context.done();
    };
    

讓我們詳述此程式碼的功能:

  • 由於此函式會變更資料,因此,我們預期 HTTP 要求是 POST,且書籤資料是要求本文的一部分。
  • Azure Cosmos DB 輸入繫結會嘗試使用我們收到的 id 來擷取文件或書籤。 如果找到項目,則會設定 bookmark 物件。 if(bookmark) 條件會檢查,以查看是否找到項目。
  • 新增到資料庫,就像將 context.bindings.newbookmark 繫結參數設定為新的書籤項目一樣簡單 (我們已將該項目建立為 JSON 字串)。
  • 將訊息張貼到我們的佇列就像是設定 context.bindings.newmessage 參數一樣簡單。

注意

您唯一需要執行的工作就是建立佇列繫結。 您從未明確建立佇列。 您將見證繫結的強大能力! 如下列通知所宣告,如果佇列不存在,即會自動為您建立。

此螢幕擷取畫面顯示將自動建立佇列的訊息。

  1. 請從 <functionapp> \ HttpTrigger3 \ 路徑的下拉式清單中,選取 function.json,並進行下列變更:

    1. "collectionName" 的所有執行個體變更為 "containerName"
    2. "connectionStringSetting" 的所有執行個體變更為 "connection"
    3. 刪除 "methods": [] 的參考。
  2. 您的最終 function.json 檔案應類似此程序碼。

    {
      "bindings": [
        {
          "authLevel": "function",
          "type": "httpTrigger",
          "direction": "in",
          "name": "req",
          "methods": [
            "get",
            "post"
          ]
        },
        {
          "type": "http",
          "direction": "out",
          "name": "res"
        },
        {
          "name": "bookmark",
          "direction": "in",
          "type": "cosmosDB",
          "partitionKey": "{id}",
          "databaseName": "func-io-learn-db",
          "containerName": "Bookmarks",
          "connection": "your-database_DOCUMENTDB",
          "id": "{id}"
        },
        {
          "name": "newbookmark",
          "direction": "out",
          "type": "cosmosDB",
          "partitionKey": "/id",
          "databaseName": "func-io-learn-db",
          "containerName": "Bookmarks",
          "connection": "your-database_DOCUMENTDB"
        },
        {
          "name": "newmessage",
          "direction": "out",
          "type": "queue",
          "queueName": "bookmarks-post-process",
          "connection": "your-storage-account_STORAGE"
        }
      ]
    }
    
  3. 在命令列中,選取 [儲存]

這樣就大功告成了。 我們將在下一節說明實際運作情形。

  1. 若要在程式碼編輯器中開啟 run.ps1 檔案,從窗格頂端的階層連結選取 HttpTrigger3 函式。

  2. 在 [函式] 功能表的 [開發人員] 底下,選取 [編碼 + 測試]HttpTrigger3 函式的 [編碼 + 測試] 窗格隨即出現,其中顯示 run.ps1 的預設內容。

  3. 以下列程式碼取代檔案中的內容。

    using namespace System.Net
    
    param($Request, $bookmark, $TriggerMetadata)
    
    if ($bookmark) {
        $status = 422
        $body = "Bookmark already exists."
    }
    else {
        $newBookmark = @{ id = $Request.Body.id; url = $Request.Body.url }
    
        Push-OutputBinding -Name newbookmark -Value $newBookmark
    
        Push-OutputBinding -Name newmessage -Value $newBookmark
    
        $status = [HttpStatusCode]::OK
        $body = "bookmark added!"
    }
    
    Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
        StatusCode = $status
        Body = $body
        ContentType = "application/json"
    })
    
  4. 選取命令列中的儲存。 隨即會建立連線並開啟記錄檔工作階段。

讓我們詳述此程式碼的功能:

  • 由於此函式會變更資料,因此,我們預期 HTTP 要求是 POST,且書籤資料是要求本文的一部分。
  • Azure Cosmos DB 輸入繫結會嘗試使用要求中的 id 來擷取文件或書籤。 如果找到項目,則會設定 bookmark 物件。 if ($bookmark) 條件會檢查,以查看是否找到項目。
  • 新增到資料庫,就像使用 Cosmos DB 輸出繫結 (newbookmark) 的名稱與 $newBookmark 物件的值來呼叫 Push-OutputBinding 一樣簡單。
  • 將訊息張貼到我們的佇列就像使用佇列輸出繫結 (newmessage) 與 $newBookmark 物件的值呼叫 Push-OutputBinding 一樣。

注意

您唯一需要執行的工作就是建立佇列繫結。 您從未明確建立佇列。 您將見證繫結的強大能力! 如下列通知所宣告,如果佇列不存在,即會自動為您建立。

此螢幕擷取畫面顯示將自動建立佇列的 UI 工具提示。

這樣就大功告成了。 我們將在下一節說明實際運作情形。

試試看

現在我們有多個輸出繫結,測試起來會更困難。 在先前的單元中,我們透過利用查詢字串傳送 HTTP 要求來測試內容,但這次會執行 HTTP 貼文。 我們也需要確認訊息也已成功加入佇列中。

  1. HttpTrigger3 函式之 [編碼 + 測試] 窗格的命令列中,選取 [測試/執行]。 隨即出現新窗格,並開啟 [輸入] 索引標籤,如下圖所示:

    此螢幕擷取畫面顯示 [測試/執行] 窗格。

  2. 在 [HTTP 方法] 下拉式清單中,確認已選取 [POST]

  3. 將要求本文的內容取代為下列 JSON 物件:

    {
        "id": "docs",
        "url": "https://learn.microsoft.com/azure"
    }
    
  4. 選取執行

  5. 程式設計進度會顯示在 [記錄] 窗格中。 完成時,確認 [輸出] 索引標籤會在 [HTTP 回應內容] 設定中顯示「書籤已經存在」。

    [輸出] 索引標籤的螢幕擷取畫面,其中顯示「書籤已經存在」回應。

    您已在練習 - 使用輸入繫結讀取資料中新增書籤項目。 回應會確認您的 var bookmark = context.bindings.bookmark JavaScript 正常運作,且您的 PowerShell 程式碼正在建立相同的連線。

  6. 讓我們將第二個書籤張貼到資料庫。 選取 [輸入] 索引標籤。

  7. 將要求本文的內容取代為下列 JSON 物件:

    {
        "id": "github",
        "url": "https://www.github.com"
    }
    
  8. 選取執行

  9. 確認 [輸出] 索引標籤會在 [HTTP 回應內容] 中顯示「已新增書籤!」,如下列螢幕擷取畫面所示。

    [輸出] 索引標籤的螢幕擷取畫面,其中顯示「已新增書籤」回應。

恭喜! 您的函式會如設計般運作! 但是,我們新增到程式碼的佇列作業呢? 讓我們看看是否有任何項目寫入到佇列。

確認有訊息寫入到佇列

Azure 佇列儲存體的佇列會裝載於儲存體帳戶中。 您在建立輸出繫結時設定了儲存體帳戶。

  1. 在 Azure 入口網站的全域搜尋列中,輸入儲存體帳戶,然後在結果清單中選取 [儲存體帳戶]。 [儲存體帳戶] 窗格隨即出現。

    此螢幕擷取畫面顯示儲存體帳戶搜尋的搜尋結果。

  2. 選取您用來設定 newmessage 輸出繫結的儲存體帳戶。

  3. 在 [儲存體帳戶] 功能表的 [資料儲存體] 底下,選取 [佇列] 來列出此儲存體帳戶所裝載的佇列。 確認已列出 bookmarks-post-process 佇列,如下列螢幕擷取畫面所示。

    此螢幕擷取畫面顯示此儲存體帳戶所裝載的佇列。

  4. 選取 [bookmarks-post-process],以列出佇列中的訊息。 如果一切都照計劃進行,佇列會包含您將書籤新增至資料庫時所張貼的訊息。 它應該如下所示。

    此螢幕擷取畫面顯示含有兩則訊息的訊息佇列。

    在此範例中,訊息已獲指定唯一識別碼,而且 [訊息文字] 資料行會以 JSON 格式顯示您的書籤。 沒有任何適用於您嘗試新增之 Azure docs 書籤的訊息,因為它已存在於資料庫中。

  5. 您可以使用新的識別碼/URL 集合來變更測試窗格中的要求本文並執行函式,來進一步測試函式。 監看此佇列來查看更多抵達的訊息。 您也可以查看資料庫確認已新增項目。

在此練習中,我們已將您對繫結的了解擴展到輸出繫結,並將資料寫入到 Azure Cosmos DB。 我們已新增輸出繫結來將訊息張貼到 Azure 佇列。 此範例會示範繫結的真正強大能力,可協助您將資料成形,並將資料從傳入來源移至各種目的地。 我們不需撰寫任何資料庫程式碼,也不需要自行管理連接字串。 相反地,我們以宣告方式設定了繫結,並讓平台負責保護連線、調整函式及調整連線。