在 Azure Cosmos DB for NoSQL SDK 中对叉积查询结果进行分页
Azure Cosmos DB 查询通常会有多页的结果。 当 Azure Cosmos DB 不能在单次执行中返回所有查询结果时,分页会在服务器端自动完成。 在许多应用程序中,你需要使用 SDK 编写代码,以高性能的方式分批处理查询结果。
在本实验室中,你将创建一个可在循环中使用的源迭代器,用来循环访问整个结果集。
准备开发环境
如果你还没有将 DP-420 的实验室代码存储库克隆到使用此实验室的环境,请按照以下步骤操作。 否则,请在 Visual Studio Code 中打开以前克隆的文件夹。
-
启动 Visual Studio Code。
📝 如果你还不熟悉 Visual Studio Code 界面,请参阅 Visual Studio Code 入门指南
-
打开命令面板并运行 Git: Clone,将
https://github.com/microsoftlearning/dp-420-cosmos-db-dev
GitHub 存储库克隆到你选择的本地文件夹中。💡 你可以使用 Ctrl+Shift+P 键盘快捷方式打开命令面板。
-
克隆存储库后,打开在 Visual Studio Code 中选择的本地文件夹。
创建 Azure Cosmos DB for NoSQL 帐户
Azure Cosmos DB 是一项基于云的 NoSQL 数据库服务,它支持多个 API。 在首次预配 Azure Cosmos DB 帐户时,可以选择希望该帐户支持的 API(例如 Mongo API 或 NoSQL API)。 完成 Azure Cosmos DB for NoSQL 帐户预配后,可以检索终结点和密钥,并使用它们通过 Azure SDK for .NET 或所选择的任何其他 SDK 连接到 Azure Cosmos DB for NoSQL 帐户。
-
在新的 Web 浏览器窗口或选项卡中,导航到 Azure 门户 (
portal.azure.com
)。 -
使用与你的订阅关联的 Microsoft 凭证登录到门户。
-
选择“+ 创建资源”,搜索“Cosmos DB”,然后使用以下设置创建新的“Azure Cosmos DB for NoSQL”帐户资源,并将所有其余设置保留为默认值:
设置 值 订阅 你的现有 Azure 订阅 资源组 选择现有资源组,或创建新资源组 帐户名 输入全局唯一名称 位置 选择任何可用区域 容量模式 预配的吞吐量 应用免费分级折扣 不应用 📝 你的实验室环境可能存在阻止你创建新资源组的限制。 如果是这种情况,请使用现有的预先创建的资源组。
-
等待部署任务完成,然后继续执行此任务。
-
转到新创建的 Azure Cosmos DB 帐户资源,并导航到“键”窗格。
-
此窗格包含从 SDK 连接到帐户所需的连接详细信息和凭据。 具体而言:
-
请注意“URI”** 字段。 稍后在本练习中将用到此终结点值。
-
请注意“主键”** 字段。 稍后在本练习中将用到此键值。
-
-
返回到 Visual Studio Code。
使用数据为 Azure Cosmos DB for NoSQL 帐户设定种子
cosmicworks 命令行工具将示例数据部署到任何 Azure Cosmos DB for NoSQL 帐户。 该工具是开源工具,可通过 NuGet 获得。 将此工具安装到 Azure Cloud Shell,然后使用它来设定数据库种子。
-
在 Visual Studio Code 中,打开“终端”菜单,然后选择“新建终端”以打开新的终端实例 。
-
在计算机上安装可全局使用的 cosmicworks 命令行工具。
dotnet tool install cosmicworks --global --version 1.*
💡 此命令可能需要几分钟时间才能完成。 如果你过去已经安装了此工具的最新版本,此命令将输出警告消息(*工具 “cosmicworks” 已安装)。
-
使用以下命令行选项运行 cosmicworks 以设置 Azure Cosmos DB 种子帐户:
选项 值 –endpoint 之前在本实验室中复制的终结点值 –key 之前在本实验室中复制的键值 –datasets product cosmicworks --endpoint <cosmos-endpoint> --key <cosmos-key> --datasets product
📝 例如,如果终结点为:https://dp420.documents.azure.com:443/,密钥为:fDR2ci9QgkdkvERTQ==,则命令为:
cosmicworks --endpoint https://dp420.documents.azure.com:443/ --key fDR2ci9QgkdkvERTQ== --datasets product
-
等待 cosmicworks 命令完成对帐户的数据库、容器和项的填充。
-
关闭集成终端。
使用 SDK 对小型 SQL 查询结果集进行分页
处理查询结果时,必须确保代码处理所有结果页面,并在发出后续请求之前检查是否还有任何其他页面。
-
在 Visual Studio Code** 的“资源管理器”** 窗格中,浏览到“10-paginate-results-sdk”** 文件夹。
-
打开 product.cs 代码文件。
-
观察 Product 类及其对应的属性。 具体而言,此实验室将使用 id、name 和 price 属性。
-
返回到 Visual Studio Code 的“资源管理器”窗格,打开 script.cs 代码文件。
-
更新名为 endpoint 的现有变量,将其值设置为前面创建的 Azure Cosmos DB 帐户的终结点 。
string endpoint = "<cosmos-endpoint>";
📝 例如,如果终结点为:https://dp420.documents.azure.com:443/,则 C# 语句将为:string endpoint = “https://dp420.documents.azure.com:443/”;。
-
更新名为 key 的现有变量,将其值设置为前面创建的 Azure Cosmos DB 帐户的键 。
string key = "<cosmos-key>";
📝 例如,如果键为:fDR2ci9QgkdkvERTQ==,则 C# 语句应为:string key = “fDR2ci9QgkdkvERTQ==”;。
-
使用 SELECT p.id, p.name, p.price FROM products p 的值创建一个名为 sql 的 string 类型的新变量****:
string sql = "SELECT p.id, p.name, p.price FROM products p ";
-
创建一个 QueryDefinition 类型的新变量,并传入 sql 变量作为构造函数的参数:
QueryDefinition query = new (sql);
-
使用默认空构造函数创建名为 options** 的 QueryRequestOptions 类型的新变量:
QueryRequestOptions options = new ();
-
将 options** 变量的 MaxItemCount 属性设置为值 50**:
options.MaxItemCount = 50;
-
通过调用 Container 类的泛型 GetItemQueryIterator 方法,创建一个名为 iterator** 的 FeedIterator<> 类型的新变量,将 query** 和 options** 变量作为参数传入:
FeedIterator<Product> iterator = container.GetItemQueryIterator<Product>(query, requestOptions: options);
-
创建一个 while** 循环,用于检查 iterator** 变量的 HasMoreResults 属性:
while (iterator.HasMoreResults) { }
-
在 while** 循环中,使用 Product** 类异步调用 iterator** 变量的 ReadNextAsync 方法,将结果存储在泛型类型 FeedResponse 的名为 products** 的变量中:
FeedResponse<Product> products = await iterator.ReadNextAsync();
-
同样在 while** 循环中,通过使用变量 product** 循环访问 products** 变量来表示 Product** 类型的实例,创建新的 foreach** 循环:
foreach (Product product in products) { }
-
在 foreach** 循环中,使用内置的 Console.WriteLine** 静态方法格式化并输出 product** 变量的 id、name** 和 price** 属性:
Console.WriteLine($"[{product.id}]\t[{product.name,40}]\t[{product.price,10}]");
-
返回到 while** 循环中,使用内置的 Console.WriteLine** 静态方法输出消息“按任意键获取更多结果”**:
Console.WriteLine("Press any key to get more results");
-
同样在 while** 循环中,使用内置的 Console.ReadKey** 静态方法侦听下一个按键输入:
Console.ReadKey();
-
完成后,代码文件现在应包含:
using System; using Microsoft.Azure.Cosmos; string endpoint = "<cosmos-endpoint>"; string key = "<cosmos-key>"; CosmosClient client = new CosmosClient(endpoint, key); Database database = await client.CreateDatabaseIfNotExistsAsync("cosmicworks"); Container container = await database.CreateContainerIfNotExistsAsync("products", "/categoryId"); string sql = "SELECT p.id, p.name, p.price FROM products p "; QueryDefinition query = new (sql); QueryRequestOptions options = new (); options.MaxItemCount = 50; FeedIterator<Product> iterator = container.GetItemQueryIterator<Product>(query, requestOptions: options); while (iterator.HasMoreResults) { FeedResponse<Product> products = await iterator.ReadNextAsync(); foreach (Product product in products) { Console.WriteLine($"[{product.id}]\t[{product.name,40}]\t[{product.price,10}]"); } Console.WriteLine("Press any key for next page of results"); Console.ReadKey(); }
-
保存 script.cs 文件。
-
在 Visual Studio Code** 中,打开 10-paginate-results-sdk** 文件夹的上下文菜单,然后选择“在集成终端中打开”** 以打开一个新的终端实例。
-
使用 dotnet run 命令生成并运行项目:
dotnet run
-
该脚本现在将输出与查询匹配的第一组 50 个项。 按任意键获取下一组 50 个项,直到查询循环访问完所有匹配项。
💡 查询将匹配 products 容器中的数百个项。
-
关闭集成终端。
-
关闭 Visual Studio Code。