JavaScript:使用 Azure 函数将数据存储在 MongoDB 中

创建 Azure 函数 API,将数据与 Mongoose API 一起存储在 Cosmos DB 中,然后将 Function 应用程序部署到 Azure 云,以便使用公共 HTTP 终结点进行托管。

显示通过 Azure 函数传递数据的 HTTP 请求路径并在 Cosmos D B 中存储的流程图。

此 Azure 函数应用的完整源代码:

准备开发环境

安装以下软件:

稍后将在本教程中安装以下软件:

1.在 Visual Studio Code 登录到 Azure

如果你已使用 Azure 服务扩展,则应该已经登录,可以跳过此步骤。

在 Visual Studio Code 中安装 Azure 服务扩展后,需要登录到 Azure 帐户。

  1. 在Visual Studio Code中,通过在主侧栏中选择 Azure 图标或使用键盘快捷方式 (Shift + Alt + A) 打开 Azure 资源管理器。

  2. 在“ 资源 ”部分中,选择“ 登录到 Azure”,然后按照提示进行操作。

    通过 VS Code 登录到 Azure

  3. 登录后,验证 Azure 帐户的电子邮件地址是否显示在“状态栏”中,以及订阅是否显示在 Azure 资源管理器中:

    VS Code 的 Azure 资源管理器,其中显示了订阅

2.创建 Azure 资源组

资源组是基于区域的资源集合。 先创建资源组,再创建该组中的资源,这样在本教程结束时就可以删除资源组,而不必单独删除每个资源。

  1. 在Visual Studio Code中,通过在主侧栏中选择 Azure 图标或使用键盘快捷方式 (Shift + Alt + A) 打开 Azure 资源管理器。

  2. “资源 ”下找到订阅, + 然后选择图标,然后选择“ 创建资源组”。

  3. 使用下表,根据提示完成操作:

    Prompt
    输入新资源组的名称。 cosmosdb-mongodb-function-resource-group
    选择新资源的位置。 选择一个离你近的地理区域。

3.创建本地 Functions 应用

创建一个本地 Azure Functions(无服务器)应用程序,其中包含一个 HTTP 触发器函数。

  1. 在Visual Studio Code中,通过在主侧栏中选择 Azure 图标或使用键盘快捷方式 (Shift + Alt + A) 打开 Azure 资源管理器。

  2. “工作区” 部分中,选择 +创建函数”。

    在 VS Code 中创建本地函数应用

  3. 此时会显示一个弹出窗口,询问是否要创建新项目? 请选择“是”。

  4. 使用下表完成本地 Azure 函数项目的创建:

    Prompt Value 说明
    选择一种语言 TypeScript
    为项目的第一个函数选择模板 HTTP 触发器 API 是使用 HTTP 请求调用的。
    提供函数名称 category API 路由是 /api/category
    授权级别 功能 这会锁定远程 API,使其处理随请求传递函数密钥的请求。 在本地开发时,无需函数密钥。
  5. Visual Studio Code完成项目创建后,请使用文件资源管理器 Ctrl + Shift + D 查看项目,其中包含一个名为函数的文件夹,类别包含三个文件:

    文件名 说明
    index.ts 响应 HTTP 请求的源代码。
    function.json HTTP 触发器的绑定配置
    sample.dat 一个占位符数据文件,用于演示文件夹中可以有其他文件。 如果需要,可以删除此文件,因为本教程中没有使用它。
  6. 在Visual Studio Code中,打开集成的 bash 终端,Ctrl + ` 并安装 Azure 函数应用依赖项:

    npm install
    
  7. 添加本地运行 Azure Function App 所需的 Azure Function Core 工具包:

    npm install --global azure-functions-core-tools
    
  8. ./category/index.ts在文件中,添加新context.log消息以将名称打印到函数日志中,并在以下代码中突出显示:

    import { AzureFunction, Context, HttpRequest } from "@azure/functions"
    
    const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
        context.log('HTTP trigger function processed a request.');
        const name = (req.query.name || (req.body && req.body.name));
        context.log(`*** HTTPExample name: ${name}`);
        const responseMessage = name
            ? "Hello, " + name + ". This HTTP triggered function executed successfully."
            : "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.";
    
        context.res = {
            // status: 200, /* Defaults to 200 */
            body: responseMessage
        };
    
    };
    
    export default httpTrigger;
    

4.运行本地无服务器函数

在本地运行 Azure Functions 项目,以在部署到 Azure 之前对其进行测试。

  1. 在Visual Studio Code中,打开./category/index.ts文件,在函数末尾的最后块上context.res设置断点。

  2. 在Visual Studio Code中,按 F5 启动调试器并附加到Azure Functions主机。

    还可以使用“调试”>“启动调试”菜单命令 。

  3. Functions Core 工具的输出显示在 终端 面板中。

    本地调试时 VSCode 输出终端面板的部分屏幕截图

  4. 在Visual Studio Code中,通过在主侧栏中选择 Azure 图标或使用键盘快捷方式 (Shift + Alt + A) 打开 Azure 资源管理器。

  5. “工作区”部分中,查找并展开“本地项目 ->Functions类别>。

  6. 右键单击函数名称、 类别,然后选择“ 复制函数 URL”。

    Visual Studio Code的部分屏幕截图,其中突出显示了“复制函数 URL”的 Azure 函数按钮。

  7. 在浏览器中,粘贴 URL,然后添加到 ?name=YOUR-NAME URL 末尾,替换为 YOUR-NAME 名称:

    显示 HTTP 触发器函数分析 URL 参数结果的 Web 浏览器的屏幕截图。

    函数在本地运行,因此本地 API 不需要函数密钥也可成功工作。

  8. 在 VS Code 中,当断点命中时,请查看变量和调用堆栈。 单步执行断点以让函数完成。

  9. (可选)若要查看整个 HTTP 响应,请使用终端中的以下 cURL 命令:

    curl http://localhost:7071/api/category?name=john --verbose
    

    响应为:

    *   Trying ::1:7071...
    *   Trying 127.0.0.1:7071...
    * Connected to localhost (127.0.0.1) port 7071 (#0)
    > GET /api/category?name=john HTTP/1.1
    > Host: localhost:7071
    > User-Agent: curl/7.75.0
    > Accept: */*
    >
    * Mark bundle as not supporting multiuse
    < HTTP/1.1 200 OK
    < Date: Tue, 21 Sep 2021 17:35:05 GMT
    < Content-Type: text/plain; charset=utf-8
    < Server: Kestrel
    < Transfer-Encoding: chunked
    < Request-Context: appId=cid-v1:e981b763-c455-4e32-852c-73765b048a0f
    <
    Hello, john. This HTTP triggered function executed successfully.* Connection #0 to host localhost left intact
    
  10. 在 VS Code 中,停止调试器 Shift + F5

5. 在 Visual Studio Code 中创建 Azure 函数应用

在本部分中,你将在 Azure 订阅中创建函数应用和相关的资源。

  1. 在活动栏中选择 Azure 图标。 然后在“资源”区域中,选择 + 图标,然后选择“在 Azure 中创建函数应用”选项。

  2. 根据提示提供以下信息:

    Prompt 选择
    选择订阅 选择要使用的订阅。 如果你在“资源”下只有一个订阅可见,则你不会看到此提示。
    输入函数应用的全局唯一名称 键入在 URL 路径中有效的名称。 将对你键入的名称进行验证,以确保其在 Azure Functions 中是唯一的。
    选择一个运行时堆栈 选择你一直在本地运行的语言版本。
    选择新资源的位置 为了获得更好的性能,请选择你附近的区域

    在 Azure 中创建各个资源时,该扩展会在“Azure: 活动日志”面板中显示这些资源的状态。

6. 在 Visual Studio Code 中将 Azure 函数应用部署到 Azure

重要

部署到现有函数应用将始终覆盖该应用在 Azure 中的内容。

  1. 在“活动”栏中选择 Azure 图标,然后在 “资源 ”区域中,右键单击函数应用资源,然后选择“ 部署到函数应用 ”按钮。
  2. 如果系统询问是否确定要部署,请选择“ 部署”。
  3. 部署完成后,会显示一个通知,其中包含多个选项。 选择 “查看输出 ”以查看结果。 如果错过了通知,请选择右下角的响铃图标以再次查看。

7. 运行远程无服务器函数

  1. 在Visual Studio Code中,通过选择主侧栏中的 Azure 图标或使用键盘快捷方式 (Shift + Alt + A) 打开 Azure 资源管理器。

  2. 在“ 资源 ”部分中,展开 Azure 函数应用资源。 右键单击函数名称, category在 Functions 节点中,然后选择 “复制函数 URL” :

    复制函数 URL 命令

  3. 将 URL 粘贴到浏览器中。 URL 包括函数键, code作为查询参数。

  4. 将查询字符串名称/值对 &name=YOUR-NAME 追加到 URL。 浏览器会显示在云中成功运行的函数。

    显示 API 的结果成功返回的浏览器屏幕截图。

  5. 现在从 URL 中删除 code= 查询字符串参数,然后再次在浏览器中提交 URL。 这会模拟到受保护的 API 的未经授权的请求。

    显示 API 的结果返回 HTTP 错误代码 401 的浏览器屏幕截图。

  6. 在 Visual Studio Code 中查看流式处理日志,找到 context.log 输出。

8. 添加 Cosmos DB for MongoDB API 集成

Cosmos DB 提供 MongoDB API 来提供熟悉的集成点。

  1. 在Visual Studio Code中,通过选择主侧栏中的 Azure 图标或使用键盘快捷方式 (Shift + Alt + A) 打开 Azure 资源管理器。

  2. 在“ 资源 ”部分中,选择 +创建数据库服务器”。 使用下表完成提示,以创建新的 Azure Cosmos DB 资源。

    Prompt Value 说明
    选择 Azure 数据库服务器 “用于 MongoDB 的 Azure Cosmos DB”API
    提供 Cosmos DB 帐户名称。 cosmosdb-mongodb-database 该名称为 API 的 URL 的一部分。
    选择容量模型。 预配的吞吐量
    选择新资源的资源组。 cosmosdb-mongodb-function-resource-group 选择或创建资源组
    选择新资源的位置。 选择建议的区域。
  3. 在Visual Studio Code终端中,Ctrl + Shift + `,然后安装 npm 包:

    npm install mongoose
    
  4. In Visual Studio Code, create a subdirectory named lib, create a file named ./azure-cosmosdb-mongodb.ts and copy the following code into it.

    import { Schema, model, connect } from "mongoose";
    
    let db=null;
    
    const CategorySchema = new Schema(
      { categoryName: String },
      { timestamps: true }
    );
    const CategoryModel = model("Category", CategorySchema, "Bookstore");
    
    export const init = async () => {
      if(!db) {
        db = await connect(process.env["CosmosDbConnectionString"]);
      }
    };
    export const addItem = async (doc) => {
      const modelToInsert = new CategoryModel();
      modelToInsert["categoryName"] = doc.name;
    
      return await modelToInsert.save();
    };
    export const findItemById = async (id) => {
      return await CategoryModel.findById(id);
    };
    export const findItems = async (query = {}) => {
      return await CategoryModel.find({});
    };
    export const deleteItemById = async (id) => {
      return await CategoryModel.findByIdAndDelete(id);
    };
    

    此文件包含 Category 容器的简单 mongoose 架构。

  5. 在 Visual Studio Code 中,打开 ./category/index.ts 文件,将整个文件的代码替换为以下内容:

    import { AzureFunction, Context, HttpRequest } from "@azure/functions";
    import * as db from "../lib/azure-cosmosdb-mongodb";
    
    const httpTrigger: AzureFunction = async function (
      context: Context,
      req: HttpRequest
    ): Promise<void> {
      try {
        let response = null;
    
        // create 1 db connection for all functions
        await db.init();
    
        switch (req.method) {
          case "GET":
            if (req?.query.id || (req?.body && req?.body?.id)) {
              response = {
                documentResponse: await db.findItemById(req?.body?.id),
              };
            } else {
              // allows empty query to return all items
              const dbQuery =
                req?.query?.dbQuery || (req?.body && req?.body?.dbQuery);
              response = {
                documentResponse: await db.findItems(dbQuery),
              };
            }
            break;
          case "POST":
            if (req?.body?.document) {
              const insertOneResponse = await db.addItem(req?.body?.document);
              response = {
                documentResponse: insertOneResponse,
              };
            } else {
              throw Error("No document found");
            }
    
            break;
          case "DELETE":
            if (req?.query?.id || (req?.body && req?.body?.id)) {
              response = {
                documentResponse: await db.deleteItemById(req?.body?.id),
              };
            } else {
              throw Error("No id found");
            }
    
            break;
          default:
            throw Error(`${req.method} not allowed`)
        }
    
        context.res = {
          body: response,
        };
      } catch (err) {
        context.log(`*** Error throw: ${JSON.stringify(err)}`);
    
        context.res = {
          status: 500,
          body: err,
        };
      }
    };
    
    export default httpTrigger;
    
  6. 在 Visual Studio Code 中,打开 ./category/function.json 文件,并更改方法属性以包括 delete。

    {
      "bindings": [
        {
          "authLevel": "function",
          "type": "httpTrigger",
          "direction": "in",
          "name": "req",
          "methods": [
            "get",
            "post",
            "delete"
          ]
        },
        {
          "type": "http",
          "direction": "out",
          "name": "res"
        }
      ],
      "scriptFile": "../dist/category/index.js"
    }
    

9. 将远程 Cosmos DB 数据库连接字符串添加到本地Node.js无服务器项目

  1. 在Visual Studio Code中,通过选择主侧栏中的 Azure 图标或使用键盘快捷方式 (Shift + Alt + A) 打开 Azure 资源管理器。

  2. 在“ 资源 ”部分中,右键单击 Cosmos DB 数据库,然后选择 “复制连接字符串”。

    Visual Studio Code 的部分屏幕截图,其中的 Azure 资源管理器已选中数据库,以及右键单击菜单突出显示了“复制连接字符串”。

  3. 打开 ./local.settings.json 文件并添加新属性 CosmosDbConnectionString,然后粘贴数据库连接字符串作为值。

    {
      "IsEncrypted": false,
      "Values": {
        
        "FUNCTIONS_WORKER_RUNTIME": "node",
        "CosmosDbConnectionString": ""
      }
    }
    

10. 使用 Azure 函数 API

使用 cURL 命令将项添加到具有无服务器 API 的数据库

  1. 在Visual Studio Code中,按 F5 启动调试器并附加到Azure Functions主机。

  2. 在新终端 Ctrl + Shift + ` 中使用以下 cURL 命令将 John 添加到数据库:

    curl -X POST http://localhost:7071/api/category \
       -H 'Content-Type: application/json' \
       -d '{"document":{"name":"John"}}' --verbose
    
  3. 响应包含新建项的 ID:

    {
      "documentResponse": {
        "_id": "614a45d97ccca62acd742550",
        "categoryName": "John",
        "createdAt": "2021-09-21T20:51:37.669Z",
        "updatedAt": "2021-09-21T20:51:37.669Z",
        "__v": 0
      }
    }
    
  4. 在集成 bash 终端中使用以下 curl 命令将 Sally 添加到数据库:

    curl -X POST http://localhost:7071/api/category \
       -H 'Content-Type: application/json' \
       -d '{"document":{"name":"Sally"}}' --verbose
    
  5. 响应包含新建项的 ID:

    {
      "documentResponse": {
        "_id": "614a45d97bbba62acd742550",
        "categoryName": "Sally",
        "createdAt": "2021-09-21T20:51:37.669Z",
        "updatedAt": "2021-09-21T20:51:37.669Z",
        "__v": 0
      }
    }
    

使用 API 从数据库获取所有项

  1. 使用以下 curl 命令从数据库获取所有项:

    curl -X GET http://localhost:7071/api/category \
       -H 'Content-Type: application/json' --verbose
    
  2. 响应包含新建项的 ID:

    {
      "documentResponse": [
        {
          "_id": "614a45d97ccca62acd742550",
          "categoryName": "John",
          "createdAt": "2021-09-21T20:51:25.288Z",
          "updatedAt": "2021-09-21T20:51:25.288Z",
          "__v": 0
        },
        {
          "_id": "614a45d97bbba62acd742550",
          "categoryName": "Sally",
          "createdAt": "2021-09-21T20:51:37.669Z",
          "updatedAt": "2021-09-21T20:51:37.669Z",
          "__v": 0
        }
      ]
    }
    

使用适用于 Cosmos DB 的 VSCode 扩展查看所有数据

  1. 在Visual Studio Code中,通过选择主侧栏中的 Azure 图标或使用键盘快捷方式 (Shift + Alt + A) 打开 Azure 资源管理器。

  2. 在“ 资源 ”部分中,右键单击 Cosmos DB 数据库,然后选择“ 刷新”。

  3. 展开 测试 数据库和 Bookstore 集合节点以查看文档。

  4. 选择列出的项之一以查看 Cosmos DB 中的数据。

    Visual Studio Code 的部分屏幕截图,在 Azure 资源管理器的“数据库”下的读取窗格中显示了所选的项。

使用 API 从数据库获取一项

  1. 使用以下 curl 命令从数据库获取一项。 将 DOCUMENT_ID 替换为上个步骤响应中的一个 ID:

    curl -X GET http://localhost:7071/api/category \
       -H 'Content-Type: application/json' \
       -d '{"id":"DOCUMENT_ID"}' --verbose
    
  2. 响应包含新建项的 ID:

    {
      "documentResponse": {
        "_id": "614a45cd7ccca62acd74254e",
        "categoryName": "John",
        "createdAt": "2021-09-21T20:51:25.288Z",
        "updatedAt": "2021-09-21T20:51:25.288Z",
        "__v": 0
      }
    }
    
  3. 返回到 Visual Studio Code 中的 Azure 资源管理器的“数据库”部分,右键单击 Cosmos DB,然后选择“刷新”以验证该项是否已从云资源中删除。

使用 API 从数据库中删除一项

  1. 使用以下 curl 命令从数据库中删除一项。 将 DOCUMENT_ID 替换为上个步骤响应中的一个 ID:

    curl -X DELETE http://localhost:7071/api/category \
       -H 'Content-Type: application/json' \
       -d '{"id":"DOCUMENT_ID"}' --verbose
    
  2. 响应包含新建项的 ID:

    {
      "documentResponse": {
        "_id": "614a45cd7ccca62acd74254e",
        "categoryName": "John",
        "createdAt": "2021-09-21T20:51:25.288Z",
        "updatedAt": "2021-09-21T20:51:25.288Z",
        "__v": 0
      }
    }
    
  3. 在 VS Code 中,停止调试器 Shift + F5

11. 重新部署函数应用以包含数据库代码

  1. 在Visual Studio Code中,通过选择主侧栏中的 Azure 图标或使用键盘快捷方式 (Shift + Alt + A) 打开 Azure 资源管理器。

  2. 在“ 资源 ”部分中,右键单击 Azure 函数应用,然后选择“ 部署到 Function App”。

    Visual Studio Code 的部分屏幕截图,在 Azure 资源管理器中突出显示了“函数部署”图标。

  3. 在弹出窗口中询问是否确定要部署,请选择“ 部署”。

  4. 等到部署完成后再继续。

12. 将 Cosmos DB 数据库连接字符串添加到远程 Azure 函数应用

  1. 在Visual Studio Code中,通过选择主侧栏中的 Azure 图标或使用键盘快捷方式 (Shift + Alt + A) 打开 Azure 资源管理器。

  2. 在“ 资源 ”部分中,找到 Cosmos DB。 右键单击资源,然后选择 “复制连接字符串”。

  3. 在同一 “资源 ”部分中,找到 Function App 并展开节点。

  4. 右键单击“应用程序设置”,然后选择“添加新设置” 。

    Visual Studio Code 的部分屏幕截图,在 Azure 资源管理器的“函数应用程序设置”下突出显示了“添加新设置”菜单项。

  5. 输入应用设置名称 CosmosDbConnectionString,然后按 Enter 键。

  6. 粘贴复制的值,然后按 Enter。

13. 使用基于云的 Azure 函数

  1. 仍在 Azure 资源管理器的 Functions 区域中,选择并展开函数,然后选择 Functions 节点,其中列出了 API、 类别

  2. 右键单击“类别”项,然后选择“复制函数 URL” 。

  3. 使用以下 cURL 命令,并替换 YOUR-FUNCTION-URL。 按终端运行每个命令。

    curl -X POST YOUR-FUNCTION-URL \
       -H 'Content-Type: application/json' \
       -d '{"document":{"name":"John"}}' --verbose
    
    curl -X POST YOUR-FUNCTION-URL \
       -H 'Content-Type: application/json' \
       -d '{"document":{"name":"Sally"}}' --verbose
    
    curl -X GET YOUR-FUNCTION-URL \
       -H 'Content-Type: application/json' --verbose
    
  4. 使用以下 cURL 命令,并将 YOUR-FUNCTION-URLDOCUMENT_ID 替换为上一命令中的 ID。 按终端运行每个命令。

    curl -X GET YOUR-FUNCTION-URL \
       -H 'Content-Type: application/json' \
       -d '{"id":"DOCUMENT_ID"}' --verbose
    
    curl -X DELETE YOUR-FUNCTION-URL \
       -H 'Content-Type: application/json' \
       -d '{"id":"DOCUMENT_ID"}' --verbose
    

14. 查询 Azure 函数日志

若要搜索日志,请使用 Azure 门户。

  1. 在Visual Studio Code中,选择 Azure 资源管理器,然后在 Functions 下右键单击函数应用,然后在门户中选择“打开”。

    这将打开 Azure 门户指向你的 Azure 函数。

  2. “设置”中选择 “Application Insights”,然后选择“ 查看 Application Insights 数据”。

    显示菜单选项的浏览器屏幕截图。从“设置”中选择 **Application Insights**,然后选择**查看 Application Insights 数据**。

    此链接将转到在使用 Visual Studio Code 创建 Azure 函数时为你创建的单独的指标资源。

  3. 在“ 监视 ”部分中,选择“ 日志”。 如果出现“查询”弹出窗口,请选择弹出窗口右上角的 X 将其关闭 。

  4. 在“新查询 1”窗格中的“表”选项卡上,双击“跟踪”表 。

    这会在查询窗口中输入 Kusto 查询traces

  5. 编辑查询来搜索自定义日志:

    traces 
    | where message startswith "***"
    
  6. 选择“运行”。

    如果日志未显示任何结果,可能是因为 HTTP 请求与 Kusto 中的日志可用性之间存在几分钟延迟。 等待几分钟,然后再次运行查询。

    显示对“跟踪”表的 Azure 门户 Kusto 查询结果的浏览器屏幕截图。

    你无需额外执行任何操作即可获取此日志记录信息:

    • 代码使用了 context.log 函数框架提供的函数。 通过使用 context(而不是 console)可将日志记录筛选为特定的单个函数。 如果函数应用具有许多函数,则这非常有用。
    • 函数应用为你添加了 Application Insights。
    • Kusto 查询工具包含在Azure 门户中。
    • 可以选择 traces ,而无需了解如何编写 Kusto 查询 ,以便从日志中获取最低信息。

清理资源

使用完资源后,请删除在此过程中创建的资源。 在以下过程中,替换为 YOUR-RESOURCE-GROUP-NAME 自己的资源组名称。

  1. 在 Visual Studio Code,仍位于 Azure 资源管理器中, (Shift + Alt + A) 。
  2. “资源 ”上下文工具栏中,选择“ 分组依据”。
  3. 在分组选项列表中,选择 “按资源组分组”。
  4. 右键单击资源组,然后选择“ 删除资源组”。

后续步骤

详细了解Azure Functions:

查看其他 Azure 扩展:

若要详细了解如何利用 Node.js 来使用 Azure,请访问以下资源: