为什么这个带有 $count=true 的 OData 查询返回一个对象? [英] Why does this OData query with $count=true return an object?
问题描述
我正在尝试弄清楚如何正确支持在我的 OData API 中返回(过滤的)数据集中的项目数.
I am trying to figure out how to correctly support returning the number of items in a (filtered) data set in my OData API.
我的理解是将 $count=true
参数添加到查询字符串应该允许这样做.
My understanding is that adding the $count=true
argument to the query string should allow for this.
现在,基于官方文档中教程中的示例,添加该参数应该会导致 Web API 返回只是一个整数:
Now, based on the example from the tutorial in the official docs, adding that parameter should cause the web API to return just an integer number:
下面的请求返回集合中的总人数.
The request below returns the total number of people in the collection.
GET serviceRoot/People?$count=true
响应负载
20
另一方面,这个被接受并且非常赞成1答案表明一个查询with $count=true
实际上会返回一个 object,其属性之一保存所述整数.它提供了一个示例端点上的示例查询:
On the other hand, this accepted and quite upvoted1 answer 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:
确实,该端点的实际结果是复杂对象
Indeed, the actual result from that endpoint is the complex object
{
"@odata.context": "https://services.odata.org/V4/Northwind/Northwind.svc/$metadata#Customers",
"@odata.count": 11,
"value": []
}
而不是单个整数的预期结果
instead of the expected result of a single integer number
11
这是为什么?我是否误解了文档?
1:在撰写本文时,该答案有 25 票赞成.
1: The answer had 25 upvotes at the time of writing.
推荐答案
主要问题是 OData v4 规范是一个不断发展的标准,因为许多实现以不同的方式处理某些请求,要么是因为标准已经改变,要么因为标准难以实现或规范中建议的行为不符合其余约定.
The main issue is that the OData v4 specification is an evolving standard, as such many implementations handle some requests differently, either because the standard has changed or because the standard was hard to implement or the suggested behavior in the spec does not conform to the rest of the conventions.
这是为什么?我误解了文档吗?
Why is this? Am I misunderstanding the documentation?
因此,您的主要问题是您正在阅读所查询 API 的错误文档.重要的是要认识到,对于标准的每个实现,开发人员可以选择它们与该标准的一致性,因此您需要阅读专门与该 API 相关的文档.
So your main issue is that you were reading the wrong documentation for the API that you were querying. It is important to recognize that with each implementation of a standard it is up to the developer to choose how conformant to that standard they are, so you need to read the documentation that goes specifically with that API.
这是 OData v4 的相关规范:
This is the specification in question for OData v4:
4.8 处理集合的计数
为了处理集合中项目数的原始值,客户端将/$count 附加到标识实体集或集合的 URL 的资源路径.
4.8 Addressing the Count of a Collection
To address the raw value of the number of items in a collection, clients append /$count to the resource path of the URL identifying the entity set or collection.
/$count
路径后缀标识集合中记录的整数计数,不应与系统查询选项 $top
、$skip 结合使用
、$orderby
、$expand
和 $format
.计数不得受到 $top
、$skip
、$orderby
或 $expand
的影响.在将任何 /$filter
路径段、或 $filter
或 $search
系统查询选项应用于集合后计算计数.
The /$count
path suffix identifies the integer count of records in the collection and SHOULD NOT be combined with the system query options $top
, $skip
, $orderby
, $expand
, and $format
. The count MUST NOT be affected by $top
, $skip
, $orderby
, or $expand
.
The count is calculated after applying any /$filter
path segments, or $filter
or $search
system query options to the collection.
在 .Net 实现中,因为 $count
是查询的结果,它需要作为查询选项管道的一部分进行评估,而不是作为路径的一部分.
In the .Net implementation because $count
is a result of a query, it needs to be evaluated as part of the query options pipeline, not as part of the path.
MS OData QueryOptions - 计数$count
系统查询选项允许客户端请求包含在响应中的资源的匹配资源的计数.$count 查询选项的布尔值是 true 或 false.
MS OData QueryOptions - Count
The$count
system query option allows clients to request a count of the matching resources included with the resources in the response. The $count query option has a Boolean value of true or false.
示例:
- 连同结果一起返回集合中的产品总数
http://host/service/Products?$count=true
- 可以通过在
$expand
子句中指定$count
查询选项来请求相关实体的计数.http://host/service/Categories?$expand=Products($count=true)
- Return, along with the results, the total number of products in the collection
http://host/service/Products?$count=true
- The count of related entities can be requested by specifying the
$count
query option within the$expand
clause.http://host/service/Categories?$expand=Products($count=true)
从实现的角度来看,将此查询选项混合到路径中打破了用于所有其他处理和 url 解析的约定,这确实是一个奇怪的问题.路径和查询.
From an implementaion point of view mixing this query option into the path breaks the convention used for all other processing and url parsing, it really is the odd one out. path and query.
在 .Net 实现中,因为 $count
支持集合扩展以及根(参见第二个示例),他们选择将值作为元数据/属性注入结果.这样,响应对于序列化目的仍然有效,并且 count 行为在使用它的地方再次保持一致.
In the .Net implementation, because $count
is supported in collection expansions as well as on the root (see the second example) they have chosen to inject the value as metadata/attributes mixed in with the results. In that way the response will still be valid for serialization purposes and the count behaviour is again consistent where ever it is used.
最后一个例子是我自己的一个 API,展示了扩展集合的属性响应,如果 $count=true
没有返回对象图,我将无法获得扩展的计数:
This last example I leave you with from one of my own APIs, demonstrating the attribute response for expanded collections, if $count=true
didn't return the object graph, I would not be able to get to the counts of the expansions at all:
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"
}
这篇关于为什么这个带有 $count=true 的 OData 查询返回一个对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!