使用 Prefer: odata.maxpagesize 请求头配合 OData 分页,以控制从 Microsoft Dataverse Web API 返回的记录数。 如果未指定数字,每个请求最多可能会返回 5,000 个表行。 对于标准表和弹性表,可以将最大页面大小指定为最多 5,000。 对于标准表和弹性表,该服务将忽略大于 5,000 的最大页面大小请求。
注释
Dataverse 不支持 $skip 查询选项,因此无法使用 $top 和 $skip 的组合进行分页。
了解如何使用 $top 查询选项来限制行数。
以下示例仅返回前两个联系人记录:
请求:
GET [Organization URI]/api/data/v9.2/contacts?$select=fullname
Accept: application/json
OData-MaxVersion: 4.0
OData-Version: 4.0
Prefer: odata.maxpagesize=2
响应:
HTTP/1.1 200 OK
OData-Version: 4.0
Preference-Applied: odata.maxpagesize=2
{
"@odata.context": "[Organization URI]/api/data/v9.2/$metadata#contacts(fullname)",
"value": [
{
"@odata.etag": "W/\"72201545\"",
"fullname": "Yvonne McKay (sample)",
"contactid": "49b0be2e-d01c-ed11-b83e-000d3a572421"
},
{
"@odata.etag": "W/\"80648695\"",
"fullname": "Susanna Stubberod (sample)",
"contactid": "70bf4d48-34cb-ed11-b596-0022481d68cd"
}
],
"@odata.nextLink": "[Organization URI]/api/data/v9.2/contacts?$select=fullname&$skiptoken=%3Ccookie%20pagenumber=%222%22%20pagingcookie=%22%253ccookie%2520page%253d%25221%2522%253e%253ccontactid%2520last%253d%2522%257bD5026A4D-D01C-ED11-B83E-000D3A572421%257d%2522%2520first%253d%2522%257b49B0BE2E-D01C-ED11-B83E-000D3A572421%257d%2522%2520%252f%253e%253c%252fcookie%253e%22%20istracking=%22False%22%20/%3E"
}
当记录数量超过请求量时,@odata.nextLink 注释会提供一个 URL,您可以将其与 GET 结合使用以返回下一页数据,如下例所示:
请求:
GET [Organization URI]/api/data/v9.2/contacts?$select=fullname&$skiptoken=%3Ccookie%20pagenumber=%222%22%20pagingcookie=%22%253ccookie%2520page%253d%25221%2522%253e%253ccontactid%2520last%253d%2522%257bD5026A4D-D01C-ED11-B83E-000D3A572421%257d%2522%2520first%253d%2522%257b49B0BE2E-D01C-ED11-B83E-000D3A572421%257d%2522%2520%252f%253e%253c%252fcookie%253e%22%20istracking=%22False%22%20/%3E
Accept: application/json
OData-MaxVersion: 4.0
OData-Version: 4.0
Prefer: odata.maxpagesize=2
响应:
HTTP/1.1 200 OK
OData-Version: 4.0
Preference-Applied: odata.maxpagesize=2
{
"@odata.context": "[Organization URI]/api/data/v9.2/$metadata#contacts(fullname)",
"value": [
{
"@odata.etag": "W/\"80648710\"",
"fullname": "Nancy Anderson (sample)",
"contactid": "72bf4d48-34cb-ed11-b596-0022481d68cd"
},
{
"@odata.etag": "W/\"80648724\"",
"fullname": "Maria Campbell (sample)",
"contactid": "74bf4d48-34cb-ed11-b596-0022481d68cd"
}
],
"@odata.nextLink": "[Organization URI]/api/data/v9.2/contacts?$select=fullname&$skiptoken=%3Ccookie%20pagenumber=%223%22%20pagingcookie=%22%253ccookie%2520page%253d%25222%2522%253e%253ccontactid%2520last%253d%2522%257bF2318099-171F-ED11-B83E-000D3A572421%257d%2522%2520first%253d%2522%257bBB55F942-161F-ED11-B83E-000D3A572421%257d%2522%2520%252f%253e%253c%252fcookie%253e%22%20istracking=%22False%22%20/%3E"
}
应缓存返回的结果或 @odata.nextLink URL 值,并使用它返回到上一页。
请勿更改 @odata.nextLink URL 值或向其追加任何查询选项。 对于每个后续页面请求,请使用原始请求中使用的相同 odata.maxpagesize 首选项值。 可以继续分页查看数据,直到结果中不再包含 @odata.nextLink 批注。
在前面的示例中,URL 值中的$skiptoken参数值@odata.nextLink包含编码的信息。 服务器会设置此编码信息来控制分页。 请勿修改编码的信息或对其进行进一步编码。 使用提供的 URL 值检索下一页。
分页记录时请勿使用 $top 查询选项
$top使用查询选项限制返回的结果数。 请勿与请求标头一起使用$topPrefer: odata.maxpagesize。 如果同时包含这两者, $top 则将被忽略。
以下示例仅返回前三个帐户行:
GET [Organization URI]/api/data/v9.2/accounts?$select=name,revenue&$top=3
排序和分页
对数据进行分页时,页面的排序方式会有很大的不同。 如果有关结果排序方式的信息不明确,则 Dataverse 无法一致或有效地返回分页数据。
指定查询的顺序。 使用 FetchXml 时,如果不向查询添加任何订单元素,Dataverse 会根据表的主键添加订单。 但是 QueryExpression 不,并且当查询指定 distinct 结果时,不会返回主键值,因此 Dataverse 无法添加此默认顺序。 必须指定分页顺序。 如果没有指定任何顺序, distinct 查询结果可能会按随机顺序返回。 OData 不提供返回唯一结果的任何选项,但在检索分页结果时仍应应用排序。
分页是动态的。 每个请求在收到时都会被独立评估。 分页 Cookie 会告知 Dataverse 上一页的位置。 借助此分页 Cookie 数据,Dataverse 可以从上一页最后一条记录之后的下一条记录开始。
分页功能在向前查询时效果最佳。 如果返回并检索之前检索的页面,则结果可能会有所不同,因为自上次检索页面以来,记录可以添加、删除或修改。 换句话说,如果页面大小为 50 并且返回,则会收到 50 条记录,但它们可能不相同 50 条记录。 如果继续向前浏览数据集的页面,则预期所有记录都以一致的顺序返回。
确定性排序非常重要
确定性排序 意味着有一种方法可以一致地计算订单。 对于给定的记录集,记录始终按相同的顺序返回。 若需保持排序与分页的一致性,必须包含某些唯一值或列值的组合,并指定其评估顺序。
非确定性示例
让我们看看一个 不确定的示例。 此数据集仅包含 状态 和 状态 信息,并筛选为仅返回处于打开 状态的记录。 结果按 状态排序。 前三个页面将被请求。 结果如下所示:
| 州 | 地位 | Page |
|---|---|---|
| 打开 | 积极 | 1 开始 |
| 打开 | 积极 | 1 |
| 打开 | 积极 | 1 结束 |
| 打开 | 积极 | |
| 打开 | 积极 | |
| 打开 | 非活动 | |
| 打开 | 非活动 |
分页 Cookie 会保存该页面最后一条记录的相关信息。 请求下一页时,不包括第一页中的最后一条记录。 但是,鉴于不确定的数据,不能保证第一页上的其他两条记录不包含在第二页上。
若要实现确定性排序,请对包含唯一值的列以及几乎唯一的值的列设置排序顺序。
确定性示例
此查询类似于 不确定的查询,但它包含包含唯一值的 Case ID 列。 它还按 状态排序,但也使用 事例 ID 进行排序。 结果如下所示:
| 州 | 地位 | 案例编号 | Page |
|---|---|---|---|
| 打开 | 积极 | Case-0010 | 1 开始 |
| 打开 | 积极 | Case-0021 | 1 |
| 打开 | 积极 | Case-0032 | 1 结束 |
| 打开 | 积极 | Case-0034 | |
| 打开 | 积极 | Case-0070 | |
| 打开 | 非活动 | Case-0015 | |
| 打开 | 非活动 | Case-0047 |
在下一页中,Cookie 将 Case-0032 作为第一页的最后一条记录存储,因此第二页将从该记录之后的下一条记录开始。 结果如下所示:
| 州 | 地位 | 案例编号 | Page |
|---|---|---|---|
| 打开 | 积极 | Case-0010 | 1 开始 |
| 打开 | 积极 | Case-0021 | 1 |
| 打开 | 积极 | Case-0032 | 1 结束 |
| 打开 | 积极 | Case-0034 | 2 启动 |
| 打开 | 积极 | Case-0070 | 2 |
| 打开 | 非活动 | Case-0015 | 2 结束 |
| 打开 | 非活动 | Case-0047 |
由于此查询对唯一列值进行排序,因此顺序是一致的。
分页数据时的排序最佳实践
注释
如果可能,查询应对表的主键进行排序,因为默认情况下,Dataverse 已针对主键进行排序进行了优化。 按非唯一字段或复杂字段排序会导致过多开销和查询速度较慢。
检索在应用程序中显示的有限数据集时,或者需要返回超过 5,000 行的数据(对于弹性表为 500 行),则需要对结果进行分页。 在确定结果顺序时所做的选择可以确定检索到的每个数据页中的行是否与其他页面重叠。 如果没有正确的排序,同一条记录可以出现在多个页面中。
若要防止同一记录出现在多个页面中,请应用以下最佳做法:
最好包含具有唯一标识符的列。 例如:
- 表主键列
- 自动编号列
- 用户/联系人 ID
如果不能包含具有唯一标识符的列,请包含多个最有可能导致唯一组合的字段。 例如:
- 名字 + 姓氏 + 电子邮件地址
- 全名 + 电子邮件地址
- 电子邮件地址 + 公司名称
分页数据时的排序反模式
以下是要避免的排序选项:
不包含唯一标识符的订单
计算字段的排序
包含单个或多个字段的排序,这些字段不太可能提供唯一性,例如:
- 状态和状态
- 选项或是非
- 仅凭名称值。 例如
name,firstnamelastname - 标题、说明和多行文本等文本字段
- 非唯一数字字段
后续步骤
了解如何聚合数据。