为什么这个带有 $count=true 的 OData 查询返回一个对象? [英] Why does this OData query with $count=true return an object?

查看:81
本文介绍了为什么这个带有 $count=true 的 OData 查询返回一个对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试弄清楚如何正确支持在我的 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:

https://services.odata.org/V4/Northwind/Northwind.svc/Customers?$count=true&$top=0&$filter=Country eq '德国'

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

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆