为什么$count=true的OData查询返回一个对象?

为什么$count=true的OData查询返回一个对象?,odata,Odata,我试图弄清楚如何正确支持在ODataAPI中返回(过滤)数据集中的项数 我的理解是,将$count=true参数添加到查询字符串应该允许这样做 现在,根据,添加该参数将导致web API仅返回一个整数: 下面的请求返回集合中的总人数 GET serviceRoot/People?$count=true 响应有效载荷 20 另一方面,表示使用$count=true的查询将实际返回一个对象,该对象的一个属性包含所述整数。它提供了一个示例性的端点查询: 实际上,该端点的实际结果是复杂对象 {

我试图弄清楚如何正确支持在ODataAPI中返回(过滤)数据集中的项数

我的理解是,将
$count=true
参数添加到查询字符串应该允许这样做

现在,根据,添加该参数将导致web API仅返回一个整数:

下面的请求返回集合中的总人数

GET serviceRoot/People?$count=true
响应有效载荷

20
另一方面,表示使用
$count=true
的查询将实际返回一个对象,该对象的一个属性包含所述整数。它提供了一个示例性的端点查询:

实际上,该端点的实际结果是复杂对象

{
  "@odata.context": "https://services.odata.org/V4/Northwind/Northwind.svc/$metadata#Customers",
  "@odata.count": 11,
  "value": []
}
而不是单个整数的预期结果

11
这是为什么?我是否误解了文档?


1:在撰写本文时,答案有25次投票。

主要问题是OData v4规范是一个不断发展的标准,因为许多实现以不同的方式处理某些请求,要么是因为标准已更改,要么是因为标准难以实现,要么是因为规范中建议的行为不符合其他约定

为什么会这样?我是不是误解了文件

因此,您的主要问题是您阅读了错误的API文档。重要的是要认识到,对于标准的每个实现,开发人员都可以选择如何符合该标准,因此您需要阅读特定于该API的文档

这是OData v4的相关规范:


要解决集合中项目数的原始值,客户端将/$count追加到标识实体集或集合的URL的资源路径

GET serviceRoot/People?$count=true
/$count
路径后缀标识集合中记录的整数计数,不应与系统查询选项
$top
$skip
$orderby
$expand
$format
组合使用。计数不得受
$top
$skip
$orderby
$expand
的影响。 将任何
/$filter
路径段,或
$filter
$search
系统查询选项应用于集合后,计算计数

GET serviceRoot/People?$count=true
在.Net实现中,由于
$count
是查询的结果,因此需要将其作为查询选项管道的一部分进行计算,而不是作为路径的一部分


$count
系统查询选项允许客户端请求响应中包含的匹配资源的计数。$count查询选项的布尔值为true或false

示例:

  • 返回集合中的产品总数以及结果
    http://host/service/Products?$count=true
  • 可以通过在
    $expand
    子句中指定
    $count
    查询选项来请求相关实体的计数。
    http://host/service/Categories?$expand=Products($count=true)
从实现的角度来看,将此查询选项混合到路径中打破了用于所有其他处理和url解析的惯例,这确实是一个奇数。路径和查询

关于对象响应 在.Net实现中,由于集合扩展和根目录都支持
$count
(请参见第二个示例),因此他们选择将值作为元数据/属性注入结果中。这样,响应对于序列化目的仍然有效,并且计数行为在使用它的任何地方都是一致的

我留给您的最后一个示例来自我自己的一个API,演示了扩展集合的属性响应,如果
$count=true
没有返回对象图,我将根本无法获得扩展的计数:

https://localhost/OData/Residents?$count=true&$expand=Entity($select=Id;$expand=Contacts($count=true;$top=0))&$select=Id&$top=2

{
    "@odata.context": "https://localhost/odata/$metadata#Residents(Id,Entity(Id,Contacts()))",
    "@odata.count": 29,
    "value": [
        {
            "Id": 13110,
            "Entity": {
                "Id": 13110,
                "Contacts@odata.count": 6,
                "Contacts": []
            }
        },
        {
            "Id": 13164,
            "Entity": {
                "Id": 13164,
                "Contacts@odata.count": 6,
                "Contacts": []
            }
        }
    ],
    "@odata.nextLink": "localhost/OData/Residents?$expand=Entity%28%24select%3DId%3B%24expand%3DContacts%28%24count%3Dtrue%3B%24top%3D0%29%29&$select=id&$top=2&$skip=2"
}