筆記:Node.js開發Azure Functions存取Azure Cosmos DB(serverless)

官方有許多文件在講述這樣的東西,我想我遭遇的問題,應該是改版所以就有點不太一樣,以下就分享我自己測試成功的方法。


一些工具的安裝建議參考我上一篇筆記:以指令部屬Azure function函數應用程式

若要Azure functions在portal中搜尋,記得要搜尋function app,記得要把app打進去。或是搜尋"函數應用程式"。

建立本機的Azure function app專案
  1. 建立專案目錄並進入目錄
  2. 使用func init初始化專案
    會建立host.json,local.setttings.json,package.json等檔案
  3. 使用git init; git add -A; git commit初始化版控
  4. 使用VSCode開啟專案目錄
  5. 安裝Azure相關外掛,azure functions,azure databases,azure storage, azure account
  6. 登入azure初始化Azure cosmos DB選擇SQL db選擇serverless模式;建立database和collection
  7. 使用VSCode或Azure Portal取得connection string並在local.setttings.json內的Values中新增一欄CosmosDbConnectionString,把connection string貼上
  8. 使用func new建立或VSCode外掛建立Azure function。後面會分別說明建立所需functions
  9. 使用func start進行local測試,會顯示URL。建議用postman測試,我有被VSCode那個"Execute function now"雷到
  10. 用VSCode外掛將Azure function app deploy上去
Azure function app專案內可以有多個Azure functions負責不同的功能,我們這裡建構read和write兩個http trigger functions。

在bindings部份我習慣用return來處理所以在兩個的functions.json中都會改設定成
{
"type": "http",
"direction": "out",
"name": "$return"
},

1. read

在function.json中加入binding到Azure Cosmos DB

{
"type": "cosmosDB",
"direction": "in",
"name": "inputDocument",
"databaseName": "my-database",
"collectionName": "my-container",
"connectionStringSetting": "CosmosDbConnectionString",
"sqlQuery": "SELECT * FROM c WHERE c.name = {name}"
}

在index.js中則是寫
module.exports = async function (context, req, inputDocument) {
if (!inputDocument || inputDocument.length === 0) {
context.log('no documents');
return { status: 404, body: 'not found' };
}

context.log('read num:', inputDocument.length);

return { status: 200, body: inputDocument };
}


2. write

在function.json中加入binding到Azure Cosmos DB

{
"type": "cosmosDB",
"direction": "out",
"name": "outputDocument",
"databaseName": "my-database",
"collectionName": "my-container",
"createIfNotExists": "false",
"connectionStringSetting": "CosmosDbConnectionString"
}

在index.js中則是寫
module.exports = async function (context, req) {
const name = (req.query.name || (req.body && req.body.name));
const number = (req.query.number || (req.body && req.body.number));

if (!name) {
context.log('write error, leak name');
return { status: 400, body: 'leak name' };
}

context.bindings.outputDocument = JSON.stringify({
name: name,
number: number,
});

return { status: 200, body: 'succeess' };
}

留言