Compartir a través de

快速入门:适用于 Node.js 的适合 MongoDB 的 Azure Cosmos DB 驱动程序

适用对象: MongoDB

开始使用 MongoDB npm 包在 Azure Cosmos DB 资源中创建数据库、集合和文档。 请按照以下步骤安装程序包并试用基本任务的示例代码。

有关适用于 MongoDB 的 API 的参考文档 | MongoDB 包 (NuGet) packages/Microsoft.Azure.Cosmos) | Azure Developer CLI

先决条件

设置

将此项目的开发容器部署到环境中。 然后,使用 Azure Developer CLI (azd) 创建 Azure Cosmos DB for MongoDB 帐户并部署容器化示例应用程序。 示例应用程序使用客户端库来管理、创建、读取和查询示例数据。

在 GitHub Codespaces 中打开

在开发容器中打开

重要

GitHub 帐户包括使用免费的存储和核心小时数的权利。 有关详细信息,请参阅包含的 GitHub 帐户存储和核心小时数

  1. 在项目的根目录中打开终端。

  2. 使用 azd auth login 向 Azure Developer CLI 进行身份验证。 按照该工具指定的步骤,使用首选 Azure 凭据向 CLI 进行身份验证。

    azd auth login
    
  3. 使用 azd init 来初始化项目。

    azd init --template cosmos-db-mongodb-nodejs-quickstart
    

    注意

    本快速入门使用 azure-samples/cosmos-db-mongodb-nodejs-quickstart 模板 GitHub 存储库。 Azure Developer CLI 会自动将此项目克隆到计算机(如果其中尚不存在该项目)。

  4. 在初始化期间,配置唯一的环境名称。

    提示

    环境名称也将用作目标资源组名称。 对于本快速入门,请考虑使用 msdocs-cosmos-db

  5. 使用 azd up 部署 Azure Cosmos DB 帐户。 Bicep 模板还部署示例 Web 应用程序。

    azd up
    
  6. 在预配过程中,选择订阅和所需位置。 等待预配过程完成。 此过程可能需要大约 5 分钟

  7. 预配 Azure 资源后,输出中将包含指向正在运行的 Web 应用程序的 URL。

    Deploying services (azd deploy)
    
      (✓) Done: Deploying service web
    - Endpoint: <https://[container-app-sub-domain].azurecontainerapps.io>
    
    SUCCESS: Your application was provisioned and deployed to Azure in 5 minutes 0 seconds.
    
  8. 使用控制台中的 URL 在浏览器中导航到 Web 应用程序。 观察正在运行的应用的输出。

    正在运行的 Web 应用程序的屏幕截图。


安装包

MongoDB npm 包添加到 JavaScript 项目。 使用 npm install package 命令指定 npm 包的名称。 dotenv 包用于在本地开发期间从 .env 文件中读取环境变量。

npm install mongodb dotenv

对象模型

在开始构建应用程序之前,我们先来了解 Azure Cosmos DB 中的资源层次结构。 Azure Cosmos DB 具有用于创建和访问资源的特定对象模型。 Azure Cosmos DB 在由帐户、数据库、集合和文档组成的层次结构中创建资源。

Azure Cosmos DB 层次结构示意图,其中包括帐户、数据库、集合和文档。

顶部是显示 Azure Cosmos DB 帐户的层次结构示意图。 帐户包含两个子数据库分片。 其中一个数据库分片包含两个子集合分片。 另一个数据库分片包含单个子集合分片。 该子集合分片包含三个子文档分片。

使用以下 MongoDB 类来与这些资源进行交互:

  • MongoClient - 此类为 Azure Cosmos DB 上的 API for MongoDB 层提供客户端逻辑表示。 此客户端对象用于对服务进行配置和执行请求。
  • Db - 此类是对服务中可能存在或可能不存在的数据库的引用。 在尝试访问该数据库或对其执行操作时,会在服务器端验证该数据库。
  • Collection - 此类是对服务中可能不存在的集合的引用。 在尝试使用该集合时,会在服务器端对其进行验证。

代码示例

本文中所述的示例代码创建名为 adventureworks 的数据库和名为 products 的集合。 products 集合设计为包含产品详细信息,例如名称、类别、数量和销售指标。 每个产品还包含一个唯一标识符。

对于此过程,数据库不会使用分片。

验证客户端

  1. 在项目目录中创建 index.js 文件。 在编辑器中,添加 requires 语句以引用 MongoDB 和 DotEnv npm 包。
// Read .env file and set environment variables
require('dotenv').config();
const random = Math.floor(Math.random() * 100);

// Use official mongodb driver to connect to the server
const { MongoClient, ObjectId } = require('mongodb');
  1. 使用构造函数定义 MongoClient, 类的新实例,并使用 process.env. 读取之前创建的环境变量。
// New instance of MongoClient with connection string
// for Cosmos DB
const url = process.env.COSMOS_CONNECTION_STRING;
const client = new MongoClient(url);

有关创建 MongoClient 实例的不同方法的详细信息,请参阅 MongoDB NodeJS 驱动程序快速入门

设置异步操作

index.js 文件中,添加以下代码以支持异步操作:

async function main(){

// The remaining operations are added here
// in the main function

}

main()
  .then(console.log)
  .catch(console.error)
  .finally(() => client.close());

应将以下代码片段添加到 main 函数中,以处理 async /await 语法。

连接到数据库

使用 MongoClient.connect 方法连接到 Azure Cosmos DB for MongoDB 资源。 connect 方法返回对数据库的引用。

// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
// ------------------------------------------------------------

// <package_dependencies> 
// Read .env file and set environment variables
require('dotenv').config();
const random = Math.floor(Math.random() * 100);

// Use official mongodb driver to connect to the server
const { MongoClient, ObjectId } = require('mongodb');
// </package_dependencies>

// <client_credentials> 
// New instance of MongoClient with connection string
// for Cosmos DB
const url = process.env.COSMOS_CONNECTION_STRING;
const client = new MongoClient(url);
// </client_credentials>

async function main(){

    // <connect_client>
    // Use connect method to connect to the server
    await client.connect();
    // </connect_client>

    // <new_database> 
    // Database reference with creation if it does not already exist
    const db = client.db(`adventureworks`);
    console.log(`New database:\t${db.databaseName}\n`);
    // </new_database>

    // <new_collection> 
    // Collection reference with creation if it does not already exist
    const collection = db.collection('products');
    console.log(`New collection:\t${collection.collectionName}\n`);
    // </new_collection>

    // <new_doc> 
    // Create new doc and upsert (create or replace) to collection
    const product = {
        category: "gear-surf-surfboards",
        name: `Yamba Surfboard-${random}`,
        quantity: 12,
        sale: false
    };
    const query = { name: product.name};
    const update = { $set: product };
    const options = {upsert: true, new: true};

    // Insert via upsert (create or replace) doc to collection directly
    const upsertResult1 = await collection.updateOne(query, update, options);
    console.log(`upsertResult1: ${JSON.stringify(upsertResult1)}\n`);
    
    // Update via upsert on chained instance
    const query2 = { _id: ObjectId(upsertResult1.upsertedId) };
    const update2 = { $set: { quantity: 20 } };
    const upsertResult2 = await client.db(`adventureworks`).collection('products').updateOne(query2, update2, options);
    console.log(`upsertResult2: ${JSON.stringify(upsertResult2)}\n`);
    // </new_doc>

    // <read_doc> 
    // Point read doc from collection:
    // - without sharding, should use {_id}
    // - with sharding,    should use {_id, partitionKey }, ex: {_id, category}
    const foundProduct = await collection.findOne({
        _id: ObjectId(upsertResult1.upsertedId), 
        category: "gear-surf-surfboards"
    });
    console.log(`foundProduct: ${JSON.stringify(foundProduct)}\n`);
    // </read_doc>

    // <create_index>
    // create index to sort by name
    const indexResult = await collection.createIndex({ name: 1 });
    console.log(`indexResult: ${JSON.stringify(indexResult)}\n`);
    // </create_index>

    // <query_docs> 
    // select all from product category
    const allProductsQuery = { 
        category: "gear-surf-surfboards" 
    };
    
    // get all documents, sorted by name, convert cursor into array
    const products = await collection.find(allProductsQuery).sort({name:1}).toArray();
    products.map((product, i ) => console.log(`${++i} ${JSON.stringify(product)}`));
    // </query_docs>

    return "done";
}

main()
  .then(console.log)
  .catch(console.error)
  .finally(() => {
    // Close the db and its underlying connections
    client.close()
  });

/*
// <console_result>
New database:   adventureworks

New collection: products

upsertResult1: {"acknowledged":true,"modifiedCount":0,"upsertedId":"62b1f492ff69395b30a03169","upsertedCount":1,"matchedCount":0}

upsertResult2: {"acknowledged":true,"modifiedCount":1,"upsertedId":null,"upsertedCount":0,"matchedCount":1}

foundProduct: {"_id":"62b1f492ff69395b30a03169","name":"Yamba Surfboard-93","category":"gear-surf-surfboards","quantity":20,"sale":false}

indexResult: "name_1"

1 {"_id":"62b1f47dacbf04e86c8abf25","name":"Yamba Surfboard-11","category":"gear-surf-surfboards","quantity":20,"sale":false}
done

清理资源

当不再需要 Azure Cosmos DB for MongoDB 帐户时,可以删除相应的资源组。

使用 az group delete 命令删除资源组。

az group delete --name $resourceGroupName

后续步骤

本快速入门介绍了如何使用 MongoDB 驱动程序创建 Azure Cosmos DB for MongoDB 帐户、数据库和集合。 你现在可以深入了解 Azure Cosmos DB for MongoDB 以导入更多数据、执行复杂的查询并管理 Azure Cosmos DB MongoDB 资源。