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

2024-04-19

我试图弄清楚如何正确支持返回 OData API 中(已过滤的)数据集中的项目数。

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

现在,基于官方文档中教程的示例 https://www.odata.org/getting-started/basic-tutorial/#count,添加该参数应该会导致 Web API 返回just一个整数:

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

GET serviceRoot/People?$count=true

响应负载

20

On the other hand, this accepted and quite upvoted1 answer https://stackoverflow.com/a/30154251/5206621 indicates that a query with $count=true will actually return an object, one of whose properties holds said integer number. It provides an exemplary query on a sample endpoint:

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

{
  "@odata.context": "https://services.odata.org/V4/Northwind/Northwind.svc/$metadata#Customers",
  "@odata.count": 11,
  "value": []
}

而不是单个整数的预期结果

11

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

1: The answer had 25 upvotes at the time of writing.


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

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

所以你的主要问题是你正在阅读wrong您正在查询的 API 的文档。重要的是要认识到,每次实施standard由开发人员决定他们与该标准的符合程度,因此您需要阅读专门与该 API 相关的文档。

这是 OData v4 的相关规范:

4.8 处理集合的计数 http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_AddressingtheCountofaCollection
为了获取集合中项目数量的原始值,客户端将 /$count 附加到标识实体集或集合的 URL 的资源路径。

The /$count路径后缀标识集合中记录的整数计数,不应与系统查询选项组合$top, $skip, $orderby, $expand, and $format。计数不得受到影响$top, $skip, $orderby, or $expand。 应用任何后计算计数/$filter路径段,或$filter or $search集合的系统查询选项。

在.Net实现中因为$count是查询的结果,需要将其作为查询选项管道的一部分而不是路径的一部分进行评估。

MS OData 查询选项 - 计数 https://learn.microsoft.com/en-us/odata/concepts/queryoptions-overview#count
The $count系统查询选项允许客户端请求响应中的资源中包含的匹配资源的计数。 $count 查询选项的布尔值为 true 或 false。

例子:

  • 返回集合中的产品总数以及结果http://host/service/Products?$count=true
  • 可以通过指定来请求相关实体的计数$count内的查询选项$expand条款。http://host/service/Categories?$expand=Products($count=true)

从实现的角度来看,混合这个查询选项进入path打破了用于所有其他处理和 url 解析的约定,这确实是一个奇怪的事情。路径和查询。

关于对象响应

在.Net实现中,因为$count在集合扩展以及根上都受支持(请参阅第二个示例),他们选择将值作为与结果混合的元数据/属性注入。这样,响应对于序列化目的仍然有效,并且count无论在何处使用,行为都再次保持一致。

最后一个示例是我从我自己的一个 API 中为您提供的,演示了扩展集合的属性响应,如果$count=true没有返回对象图,我将无法访问counts全部扩展:

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,
                "[email protected] /cdn-cgi/l/email-protection": 6,
                "Contacts": []
            }
        },
        {
            "Id": 13164,
            "Entity": {
                "Id": 13164,
                "[email protected] /cdn-cgi/l/email-protection": 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"
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐