代码之家  ›  专栏  ›  技术社区  ›  Martin Bean

返回对象中项目总数的最佳RESTful方法是什么?

  •  112
  • Martin Bean  · 技术社区  · 14 年前

    我正在为我参与的一个大型社交网站开发restapi服务。到目前为止,效果很好。我可以发布 GET , POST , PUT DELETE

    然而,通过我的API,RESTful获得成员总数的最佳方式是什么?

    目前,我向如下URL结构发出请求:

    • /api/成员 返回成员列表(如上所述,每次30个)

    我的问题是:然后如何使用类似的URL结构来获得应用程序中的成员总数?很明显只是要求 id

    11 回复  |  直到 9 年前
        1
  •  86
  •   Synchro    10 年前

    虽然对/API/users的响应是分页的,并且只返回30条记录,但是没有什么可以阻止您在响应中包括记录的总数和其他相关信息,比如页面大小、页码/偏移量等。

    StackOverflow API就是这种设计的一个很好的例子。下面是Users方法的文档- https://api.stackexchange.com/docs/users

        2
  •  81
  •   Stijn de Witt    7 年前

    分页元数据以响应头的形式包含在响应中。这种方法的最大好处是响应负载本身就是实际的数据请求者所要求的。使对分页信息不感兴趣的客户机更容易处理响应。

    在野外有一堆(标准和自定义)头文件用于返回与分页相关的信息,包括总计数。

    X-总计数

    X-Total-Count: 234
    

    some APIs 我在野外发现的。还有 NPM packages 用于将此标头的支持添加到例如环回。一些 articles 建议也设置此标题。

    它通常与 Link header,这是一个非常好的分页解决方案,但是缺少总计数信息。

    Link: </TheBook/chapter2>;
          rel="previous"; title*=UTF-8'de'letztes%20Kapitel,
          </TheBook/chapter4>;
          rel="next"; title*=UTF-8'de'n%c3%a4chstes%20Kapitel
    

    Link header 使用提供到客户端的分页链接 rel=next , rel=previous 这样做的问题是它缺少关于总共有多少条记录的信息,这就是为什么许多API将此与 X-Total-Count 标题。

    JsonApi 标准,使用 链接 格式,但将信息添加到响应信封中,而不是添加到标题中。这简化了对元数据的访问(并创建了一个添加总计数信息的位置),但增加了访问实际数据本身的复杂性(通过添加信封)。

    内容范围

    Content-Range: items 0-49/234
    

    由一篇名为 Range header, I choose you (for pagination)! . 作者为使用 Range Content-Range 分页的标头。当我们仔细阅读 the RFC 在这些头上,我们发现扩展它们的意义超出字节范围实际上是RFC预期的,并且是明确允许的。当用于 items 而不是 bytes used in the wild

    许多API,包括 the one from our favorite Q&A website 使用 ,用于添加有关数据的元信息的数据包装器。也, OData JsonApi

    这种方法(imho)的一大缺点是处理响应数据变得更加复杂,因为实际数据必须在信封的某个地方找到。还有许多不同的信封格式,你必须使用正确的。很明显,来自OData和JsonApi的响应信封有很大的不同,OData在响应的多个点混合了元数据。

    分离端点

    我认为其他的答案已经足够涵盖这一点了。我没有做过太多的调查,因为我同意这样的评论,即这是令人困惑的,因为您现在有多种类型的端点。我认为如果每个端点都代表一个(或多个)资源的集合,那就更好了。

    进一步思考

    我们不仅要传递与响应相关的分页元信息,还要允许客户机请求特定的页面/范围。有趣的是,我们也可以从这一方面来寻找一个连贯的解决方案。在这里我们也可以使用标题( 射程 /books/231/pages/52 . 我最终选择了一系列常用的请求参数,例如 pagesize page[size] limit 除了支持 头(以及作为请求参数)。

        3
  •  76
  •   Ondrej Bozek    4 年前

    对于元素的总数,我使用 X-total-count
    对于下一页、上一页等的链接,我使用HTTP Link
    http://www.w3.org/wiki/LinkHeader

    Github也是这样做的: https://developer.github.com/v3/#pagination

        4
  •  25
  •   Community Marks    7 年前

    当您不需要实际物品时,可选择

    Franci Penov's answer 当然是最好的方法,所以您总是返回项目以及所有关于所请求实体的附加元数据。这是应该做的。

    但有时返回所有数据是没有意义的,因为您可能根本不需要它们。也许你所需要的只是关于你所请求的资源的元数据。比如总页数或页数之类的。在这种情况下,您可以让URL query告诉您的服务不要返回项目,而只返回元数据,如:

    /api/members?metaonly=true
    /api/members?includeitems=0
    

    或者类似的东西。。。

        5
  •  23
  •   bzlm    14 年前

    您可以将计数作为自定义HTTP头返回,以响应HEAD请求。这样,如果客户机只需要计数,就不需要返回实际的列表,也不需要额外的URL。

    (或者,如果您处于一个从一个端点到另一个端点的受控环境中,则可以使用自定义HTTP谓词,如COUNT)

        6
  •  13
  •   adnan kamili    7 年前

    我建议添加相同的标题,例如:

    HTTP/1.1 200
    
    Pagination-Count: 100
    Pagination-Page: 5
    Pagination-Limit: 20
    Content-Type: application/json
    
    [
      {
        "id": 10,
        "name": "shirt",
        "color": "red",
        "price": "$23"
      },
      {
        "id": 11,
        "name": "shirt",
        "color": "blue",
        "price": "$25"
      }
    ]
    

    https://github.com/adnan-kamili/rest-api-response-format

    对于swagger文件:

    https://github.com/adnan-kamili/swagger-response-template

        7
  •  9
  •   Lepidopteron    5 年前

    https://tools.ietf.org/html/rfc6648 )

    我们发现“Accept Ranges”是映射分页范围的最佳选择: https://tools.ietf.org/html/rfc7233#section-2.3 https://tools.ietf.org/html/rfc7233#section-4.2 ) 不过,据说

    单位。

    这表明:使用自定义范围单位并不违反协议,但可以忽略。

    这样,我们就必须将Accept范围设置为“members”或我们期望的任何范围单位类型。此外,还将内容范围设置为当前范围。(见: https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.12

    不管怎样,我都会坚持RFC7233的建议( https://tools.ietf.org/html/rfc7233#page-8 )要发送206而不是200:


    目标资源的标头字段,指定的范围是
    有效且可满足(如第2.1节所定义),服务器应
    发送206(部分内容)响应,有效负载包含一个

    要求的范围,如第4节所定义。

    因此,我们将有以下HTTP头字段:

    对于部分内容:

    206 Partial Content
    Accept-Ranges: members
    Content-Range: members 0-20/100
    

    200 OK
    Accept-Ranges: members
    Content-Range: members 0-20/20
    
        8
  •  3
  •   willcodejavaforfood    14 年前

    GET
    /api/members/count
    

    并返回成员总数

        9
  •  2
  •   Steve Woods    14 年前

        10
  •  2
  •   Vahe Hovhannisyan    11 年前

    有时框架(比如$resource/AngularJS)需要一个数组作为查询结果,而您实际上无法得到像这样的响应 {count:10,items:[...]} 在本例中,我将“count”存储在responseHeaders中。

    另外,实际上你可以用$resource/AngularJS来实现,但是它需要一些调整。

        11
  •  0
  •   Frank Rem    4 年前

    counts 作为一种资源。URL将是:

    /api/counts/member
    
        12
  •  0
  •   Kiryl Plyashkevich    4 年前

    关于设计REST API以返回多个对象计数的有趣讨论: https://groups.google.com/g/api-craft/c/qbI2QRrpFew/m/h30DYnrqEwAJ?pli=1

    作为API使用者,我希望每个计数值都能被表示出来 作为可数资源的子资源(即GET /任务/任务计数),或作为更大 与相关资源(即GET)相关的元数据的聚合 /任务/元数据)。通过在同一父对象下限定相关终结点的范围 资源(即/任务),API变得直观,并且

    其他想法:

    1. 如果每个单独的计数仅与其他计数结合使用(例如,对于统计仪表板),则可以 公开一个端点,该端点聚合并返回当前的所有计数
    2. 如果您有一个用于列出所有资源的现有端点(即用于列出所有任务的GET/tasks),则计数可以包含在 作为元数据响应,可以作为HTTP头或在响应体中。 这样做会在API上产生不必要的负载,这可能是 根据您的用例可以忽略不计。
        13
  •  -1
  •   Wooff    10 年前

    当请求分页数据时,您知道(通过显式页面大小参数值或默认页面大小值)页面大小,因此您可以知道是否得到了所有数据的响应。当响应的数据少于页面大小时,就得到了整个数据。返回整页时,您必须再次请求另一页。

    我更喜欢为count使用单独的端点(或使用参数countOnly的相同端点)。因为您可以通过显示正确启动的progressbar来为最终用户准备长时间的过程。

    <data>
      <originalRequest>
        <filter/>
        <filter/>
      </originalReqeust>
      <totalRecordCount/>
      <pageSize/>
      <offset/>
      <list>
         <item/>
         <item/>
      </list>
    </data>
    

    我的Couleage更喜欢countOnly参数而不是现有端点。因此,当指定时,响应只包含元数据。

    终点?筛选器=值

    <data>
      <count/>
      <list>
        <item/>
        ...
      </list>
    </data>
    

    <data>
      <count/>
      <!-- empty list -->
      <list/>
    </data>