你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

适用于 JavaScript 的 Azure Cosmos DB 客户端库 - 版本 4.0.0

/TypeScript

最新 npm 徽章生成状态

Azure Cosmos DB 是一种全球分布式多模型数据库服务,支持文档、键值、宽列和图形数据库。 此包适用于 JavaScript/TypeScript 应用程序,以便与 SQL API 数据库及其包含的 JSON 文档进行交互:

  • 创建 Cosmos DB 数据库并修改其设置
  • 创建并修改容器以存储 JSON 文档集合
  • 在容器中创建、读取、更新和删除项(JSON 文档)
  • 使用类似 SQL 的语法查询数据库中的文档

关键链接:

入门

先决条件

Azure 订阅和 Cosmos DB SQL API 帐户

必须拥有 Azure 订阅Cosmos DB 帐户 (SQL API) 才能使用此包。

如果需要 Cosmos DB SQL API 帐户,可使用 Azure Cloud Shell 通过此 Azure CLI 命令创建一个帐户:

az cosmosdb create --resource-group <resource-group-name> --name <cosmos-database-account-name>

或者可在 Azure 门户中创建帐户

NodeJS

此包通过预安装 NodeJSnpm 进行分发。 应使用 Node v10 或更高版本。

CORS

如果需要针对浏览器进行开发,则需要为 Cosmos DB 帐户设置跨域资源共享 (CORS) 规则。 按照链接文档中的说明为 Cosmos DB 创建新的 CORS 规则。

安装此包

npm install @azure/cosmos

获取帐户凭据

需要 Cosmos DB 帐户终结点和密钥 。 可在 Azure 门户找到这些内容,也可使用下面的 Azure CLI 代码片段。 此代码片段已针对 Bash shell 格式化。

az cosmosdb show --resource-group <your-resource-group> --name <your-account-name> --query documentEndpoint --output tsv
az cosmosdb keys list --resource-group <your-resource-group> --name <your-account-name> --query primaryMasterKey --output tsv

创建 CosmosClient 的实例

与 Cosmos DB 的交互从 CosmosClient 类的实例开始

const { CosmosClient } = require("@azure/cosmos");

const endpoint = "https://your-account.documents.azure.com";
const key = "<database account masterkey>";
const client = new CosmosClient({ endpoint, key });

async function main() {
  // The rest of the README samples are designed to be pasted into this function body
}

main().catch((error) => {
  console.error(error);
});

为简单起见,我们已将 keyendpoint 直接包含在代码中,但你可能希望使用 dotenv 等项目或从环境变量加载,从不在源代码管理中的文件加载这些内容

在生产环境中,密钥等机密应存储在 Azure Key Vault

关键概念

初始化 CosmosClient 后,可以与 Cosmos DB 中的主要资源类型进行交互:

  • 数据库:一个 Cosmos DB 帐户可包含多个数据库。 创建数据库时,指定与文档交互时要使用的 API:SQL、MongoDB、Gremlin、Cassandra 或 Azure 表。 使用数据库对象管理其容器。

  • 容器:容器是 JSON 文档的集合。 可使用容器对象上的方法在容器中创建(插入)、读取、更新和删除项。

  • Item:项是存储在容器中的 JSON 文档。 每个项都必须包含一个具有在容器中唯一标识该项的值的 id 键。 如果未提供 id,SDK 将自动生成一个。

有关这些资源的详细信息,请参阅使用 Azure Cosmos 数据库、容器和项

示例

以下部分提供了多个代码片段,其中涵盖了一些最常见的 Cosmos DB 任务,包括:

创建数据库

CosmosClient 进行身份验证后,可以使用帐户中的任何资源。 以下代码片段创建 NOSQL API 数据库。

const { database } = await client.databases.createIfNotExists({ id: "Test Database" });
console.log(database.id);

创建容器

此示例创建具有默认设置的容器

const { container } = await database.containers.createIfNotExists({ id: "Test Database" });
console.log(container.id);

使用分区键

此示例显示了支持的各种类型的分区键。

await container.item("id", "1").read();        // string type
await container.item("id", 2).read();          // number type
await container.item("id", true).read();       // boolean type
await container.item("id", {}).read();         // None type
await container.item("id", undefined).read();  // None type
await container.item("id", null).read();       // null type

如果分区键包含单个值,则它可以作为文本值或数组提供。

await container.item("id", "1").read();
await container.item("id", ["1"]).read();

如果分区键包含多个值,则应将其作为数组提供。

await container.item("id", ["a", "b"]).read();
await container.item("id", ["a", 2]).read();
await container.item("id", [{}, {}]).read();
await container.item("id", ["a", {}]).read();
await container.item("id", [2, null]).read();

插入项

要将项插入容器,请将包含数据的对象传递给 Items.upsert。 Azure Cosmos DB 服务要求每个项都有一个 id 密钥。 如果未提供,SDK 将自动生成一个 id

本示例将多个项插入容器

const cities = [
  { id: "1", name: "Olympia", state: "WA", isCapitol: true },
  { id: "2", name: "Redmond", state: "WA", isCapitol: false },
  { id: "3", name: "Chicago", state: "IL", isCapitol: false }
];
for (const city of cities) {
  await container.items.create(city);
}

读取项

若要从容器中读取单个项,请使用 Item.read。 与使用 SQL 按 id 查询相比,此操作的成本较低。

await container.item("1", "1").read();

具有分层分区键的容器上的 CRUD

使用分层分区键创建容器

const containerDefinition = {
  id: "Test Database",
  partitionKey: {
    paths: ["/name", "/address/zip"],
    version: PartitionKeyDefinitionVersion.V2,
    kind: PartitionKeyKind.MultiHash,
  },
}
const { container } = await database.containers.createIfNotExists(containerDefinition);
console.log(container.id);

插入分层分区键定义为 - 的项 ["/name", "/address/zip"]

const item = {
  id: 1,
  name: 'foo',
  address: {
    zip: 100
  },
  active: true
}
await container.items.create(item);

从分层分区键定义为 的容器中读取单个项: ["/name", "/address/zip"],

await container.item("1", ["foo", 100]).read();

查询具有分层分区键且分层分区键定义为 - 的项 ["/name", "/address/zip"],

const { resources } = await container.items
  .query("SELECT * from c WHERE c.active = true", {
          partitionKey: ["foo", 100],
        })
  .fetchAll();
for (const item of resources) {
  console.log(`${item.name}, ${item.address.zip} `);
}

删除项

若要从容器中删除项,请使用 Item.delete

// Delete the first item returned by the query above
await container.item("1").delete();

查询数据库

Cosmos DB SQL API 数据库支持使用类似 SQL 的语法通过 Items.query 查询容器中的项:

const { resources } = await container.items
  .query("SELECT * from c WHERE c.isCapitol = true")
  .fetchAll();
for (const city of resources) {
  console.log(`${city.name}, ${city.state} is a capitol `);
}

通过将包含参数及其值的对象传递给 Items.query 来执行参数化查询:

const { resources } = await container.items
  .query({
    query: "SELECT * from c WHERE c.isCapitol = @isCapitol",
    parameters: [{ name: "@isCapitol", value: true }]
  })
  .fetchAll();
for (const city of resources) {
  console.log(`${city.name}, ${city.state} is a capitol `);
}

有关使用 SQL API 查询 Cosmos DB 数据库的详细信息,请参阅使用 SQL 查询来查询 Azure Cosmos DB 数据

更改源拉取模型

可以提取分区键、源范围或整个容器的更改源。

若要处理更改源,请创建 的 ChangeFeedPullModelIterator实例。 最初创建 ChangeFeedPullModelIterator时,必须在 内ChangeFeedIteratorOptions指定一个必需changeFeedStartFrom值,该值由读取更改的起始位置和 (分区键的资源或要提取更改的 FeedRange) 组成。 可以选择使用 maxItemCount 中的 ChangeFeedIteratorOptions 来设置每页接收的最大项目数。

注意:如果未 changeFeedStartFrom 指定任何值,则将从 Now () 提取整个容器的更改源。

更改源有四个起始位置:

  • Beginning
// Signals the iterator to read changefeed from the beginning of time.
const options = {
  changeFeedStartFrom: ChangeFeedStartFrom.Beginning();
}
const iterator = container.getChangeFeedIterator(options);
  • Time
// Signals the iterator to read changefeed from a particular point of time.
const time = new Date("2023/09/11") // some sample date
const options = {
  changeFeedStartFrom: ChangeFeedStartFrom.Time(time);
}
  • Now
// Signals the iterator to read changefeed from this moment onward.
const options = {
  changeFeedStartFrom: ChangeFeedStartFrom.Now();
}
  • Continuation
// Signals the iterator to read changefeed from a saved point.
const continuationToken = "some continuation token recieved from previous request";
const options = {
  changeFeedStartFrom: ChangeFeedStartFrom.Continuation(continuationToken);
}

下面是提取分区键的更改源的示例

const partitionKey = "some-partition-Key-value";
const options = {
  changeFeedStartFrom: ChangeFeedStartFrom.Beginning(partitionKey),
};

const iterator = container.items.getChangeFeedIterator(options);

while (iterator.hasMoreResults) {
  const response = await iterator.readNext();
  // process this response
}

由于更改源实际上是包含所有后续写入和更新项的无穷列表,因此 hasMoreResults 的值始终为 true。 在尝试读取更改源时,如果未发生新的更改,你会收到 NotModified 状态的响应。

可在此处找到更详细的使用指南和更改源示例。

错误处理

SDK 生成在操作期间可能发生的各种错误。

  1. ErrorResponse 如果操作的响应返回错误代码 >=400,则引发 。
  2. TimeoutError 如果由于超时而在内部调用中止,则会引发 。
  3. AbortError 如果任何用户传递的信号导致中止,则会引发 。
  4. RestError 如果基础系统调用因网络问题而失败,则会引发 。
  5. 任何 devDependencies 生成的错误。 例如 @azure/identity 包可能会引发 CredentialUnavailableError

下面是处理类型ErrorResponse为 、、 TimeoutErrorAbortErrorRestError的错误的示例。

try {
  // some code
} catch (err) {
  if (err instanceof ErrorResponse) {
    // some specific error handling.
  } else if (err instanceof RestError) {
    // some specific error handling.
  }
  // handle other type of errors in similar way.
  else {
    // for any other error.
  }
}

请务必正确处理这些错误,以确保应用程序可以从任何故障中正常恢复并继续按预期运行。 有关其中一些错误及其可能的解决方案的更多详细信息,可 在此处找到。

疑难解答

常规

与 Cosmos DB 交互时,服务返回的错误对应于返回给 REST API 请求的相同 HTTP 状态代码:

Azure Cosmos DB 的 HTTP 状态代码

冲突

例如,如果尝试使用已在 Cosmos DB 数据库中使用的 id 创建项,则会返回 409 错误,指示存在冲突。 以下代码片段通过捕获异常并显示有关错误的其他信息来妥善处理该错误。

try {
  await containers.items.create({ id: "existing-item-id" });
} catch (error) {
  if (error.code === 409) {
    console.log("There was a conflict with an existing item");
  }
}

转译

Azure SDK 旨在支持 ES5 JavaScript 语法和 LTS 版 Node.js。 如果需要对早期 JavaScript 运行时(如 Internet Explorer 或 Node 6)的支持,则需要在生成过程中转译 SDK 代码。

使用重试处理暂时性错误

使用 Cosmos DB 时,可能会遇到服务强制实施的速率限制所导致的暂时性错误,或者网络中断等其他暂时性问题。 有关如何处理此类故障的信息,请参阅云设计模式指南中的重试模式,以及相关的断路器模式

日志记录

启用日志记录可能有助于发现有关故障的有用信息。 若要查看 HTTP 请求和响应的日志,请将 AZURE_LOG_LEVEL 环境变量设置为 info。 或者,可以通过在 中@azure/logger调用 setLogLevel 来在运行时启用日志记录。 使用 AZURE_LOG_LEVEL 时,请确保在初始化日志记录库之前对其进行设置。 理想情况下,如果使用等 dotenv 库,请通过命令行传递它,请确保在记录库之前初始化此类库。

const { setLogLevel } = require("@azure/logger");
setLogLevel("info");

有关如何启用日志的更详细说明,请查看 @azure/logger 包文档

诊断

Cosmos 诊断功能提供对所有客户端操作的增强见解。 将 CosmosDiagnostics 对象添加到所有客户端操作的响应中。 例如

  • 点查找操作响应 - item.read()container.create()database.delete()
  • 查询操作响应 -queryIterator.fetchAll()
  • 批量和批处理操作 -item.batch()
  • 错误/异常响应对象。

将 CosmosDiagnostics 对象添加到所有客户端操作的响应中。 有 3 个 Cosmos 诊断级别、信息、调试和调试-不安全。 其中,信息只用于生产系统,并且调试和调试不安全信息应在开发和调试期间使用,因为它们消耗的资源要高得多。 可以通过 2 种方式设置 Cosmos 诊断级别

  • 采用编程方式
  const client = new CosmosClient({ endpoint, key, diagnosticLevel: CosmosDbDiagnosticLevel.debug });
  • 使用环境变量。 (环境变量设置的诊断级别比通过客户端选项设置诊断级别具有更高的优先级。)
  export AZURE_COSMOSDB_DIAGNOSTICS_LEVEL="debug"

Cosmos 诊断有三个成员

  • ClientSideRequestStatistics 类型:包含聚合诊断详细信息,包括元数据查找、重试、联系的终结点,以及有效负载大小和持续时间等请求和响应统计信息。 始终收集 (,可用于生产系统。)

  • DiagnosticNode:是一种树状结构,用于捕获详细的诊断信息。 类似于 har 浏览器中存在的录制。 此功能默认处于禁用状态,仅用于调试非生产环境。 在诊断级别收集的 (调试和调试不安全)

  • ClientConfig:在客户端初始化期间捕获与客户端配置设置相关的基本信息。 在诊断级别收集的 (调试和调试不安全)

请确保永远不要在生产环境中将诊断级别设置为 debug-unsafe ,因为此级别CosmosDiagnostics捕获请求和响应有效负载,如果选择将其记录 (默认在级别) 记录@azure/loggerverbose它。 这些有效负载可能会在日志接收器中捕获。

使用诊断

  • 由于 diagnostics 已添加到所有 Response 对象。 可以按编程方式访问 CosmosDiagnostic ,如下所示。
  // For point look up operations
  const { container, diagnostics: containerCreateDiagnostic } =
    await database.containers.createIfNotExists({
      id: containerId,
      partitionKey: {
        paths: ["/key1"],
      },
  });

  // For Batch operations
   const operations: OperationInput[] = [
    {
      operationType: BulkOperationType.Create,
      resourceBody: { id: 'A', key: "A", school: "high" },
    },
  ];
  const response = await container.items.batch(operations, "A"); 
  
  // For query operations
  const queryIterator = container.items.query("select * from c");
  const { resources, diagnostics } = await queryIterator.fetchAll();

  // While error handling
  try {
    // Some operation that might fail
  } catch (err) {
    const diagnostics = err.diagnostics
  }
  • 还可以使用 @azure/logger进行记录diagnostics,始终使用 @azure/logger 级别verbose记录诊断。 因此,如果将“诊断级别”设置为 debugdebug-unsafe 并将 @azure/logger 级别设置为 verbosediagnostics 则会记录 。

后续步骤

更多示例代码

SDK 的 GitHub 存储库中提供了多个示例。 这些示例提供了在使用 Cosmos DB 时经常遇到的其他场景的示例代码:

  • 数据库操作
  • 容器操作
  • 项目操作
  • 配置索引
  • 读取容器更改源
  • 存储过程
  • 更改数据库/容器吞吐量设置
  • 多区域写入操作

限制

目前 不支持以下功能。 有关替代选项,检查下面的“解决方法”部分。

数据平面限制:

  • 来自 DISTINCT 子查询的具有 COUNT 的查询
  • 直接 TCP 模式访问
  • 聚合跨分区查询(如排序、计数和非重复)不支持继续标记。 可流式传输的查询,如 SELECT * FROM WHERE , 支持延续标记。 请参阅“解决方法”部分,了解如何在没有继续标记的情况下执行非流式处理查询。
  • 更改源:处理器
  • 更改源:读取多个分区键值
  • 更改源拉取模型所有版本和删除模式 #27058
  • 更改源拉取模型对部分分层分区键的支持 #27059
  • 混合类型的跨分区 ORDER BY
  • 控制平面限制:

    • 获取 CollectionSizeUsage、DatabaseUsage 和 DocumentUsage 指标
    • 创建地理空间索引
    • 更新自动缩放吞吐量

    解决方法

    跨分区查询的继续标记

    可以使用 Side car 模式实现具有延续令牌支持的跨分区查询。 使用此模式还可以使用异构组件和技术来构建应用程序。

    执行不可构造的跨分区查询

    若要在不使用延续标记的情况下执行不可流的查询,可以使用所需的查询规范和选项创建查询迭代器。 以下示例代码演示如何使用查询迭代器提取所有结果,而无需继续标记:

    const querySpec = {
      query: "SELECT * FROM c WHERE c.status = @status",
      parameters: [{ name: "@status", value: "active" }],
    };
    const queryOptions = {
      maxItemCount: 10, // maximum number of items to return per page
      enableCrossPartitionQuery: true,
    };
    const querIterator = await container.items.query(querySpec, queryOptions);
    while (querIterator.hasMoreResults()) {
      const { resources: result } = await querIterator.fetchNext();
      //Do something with result
    }
    

    此方法还可用于可流式处理查询。

    控制平面操作

    通常,可以将 Azure 门户Azure Cosmos DB 资源提供程序 REST APIAzure CLIPowerShell 用于控制平面不支持的限制。

    其他文档

    有关 Cosmos DB 服务的更详细文档,请参阅 docs.microsoft.com 上的 Azure Cosmos DB 文档

    贡献

    若要为此库做出贡献,请阅读贡献指南,详细了解如何生成和测试代码。

    曝光数