【问题标题】:RESTful API for large "mash up" data pulls?用于大型“混搭”数据拉取的 RESTful API?
【发布时间】:2014-07-10 04:50:43
【问题描述】:

我最近的任务是建立一个从内部数据库到第三方产品的定期(介于每天和每周之间)数据转储的小项目。这个项目与我公司的愿望(我分享的一个)非常吻合,即开始在我们的数据之上建立一个正式的服务层/API。

我个人的偏好是这些 API 应该采用 RESTful 端点的形式 - 但是,现在我有一个我认为是一个很大的设计问题 - 让我解释一下......

看看有问题的数据拉取,这并不复杂。如果我只是要构建一个一次性查询,它在概念上看起来有点像:

select o.order_num, o.order_date, p.product_description, sr.sales_rep_name
from order o, line_item li, product p, sales_rep sr
where li.order_num = o.order_num
  and li.product_id = p.product_id
  and sr.sales_rep_id = o.sales_rep_id
  and o.order_date >= [some arbitrary date]

把我的大脑翻到“资源模式”,我可以考虑如何将这个基本数据模型转换为URI/payloads而不用太麻烦:

GET /orders/123
{ 
  "order_num": 59324, 
  "order_date": "2014-07-07", 
  "sales_rep_uri": "/salesRep/34",
  "line_items_uri": "/order/123/lineItems"
}

获取有关销售代表的更多信息:

GET /salesRep/34
{
  "sales_rep_name": "Jane Doe",
  "open_orders_uri": "/salesRep/34/orders"
}

获取有关订单项的更多信息:

GET /orders/123/lineItems
{
  "line_items": [
    {"order_uri": "/order/123", "product_uri": "/products/68"},
    {"order_uri": "/order/123", "product_uri": "/products/99"}
  ]
}

等等。我不是说它是一个完美的 API,我只是想证明它不是火箭科学,去思考如何以一种很好的规范化、面向资源的类型来表达数据模型通过 RESTful URI 的方式。但这正是设计问题发挥作用的地方......

一方面,我可以很容易地创建一个查询来解决问题,但查询的本质要求各种领域概念紧密耦合(换句话说,利用连接将所有规范化数据放在一起到一个很好的、自定义目的的非规范化结构中)。

另一方面,通过思考 RESTful API 的心理过程,我又回到了保持良好分区的道路上——例如。请求“Order 123”不应该把这个巨大的图表发回给我,在那里我可以看到完整的产品描述、销售代表的电话号码等。完整的 HATEOAS 级 RESTful API 的概念要求消费者应该做出后续 GET 仅根据需要深入了解此类详细信息。

我的问题归结为:解决这个用例似乎很容易通过直接查询来解决,而对于一个漂亮而整洁的 RESTful API 则很难做到(我正在想象它需要花费的 1000 个单独的 GET我收集了一周的数据,而不是查询运行所需的几秒钟)。是否有一些我不明白的良好 RESTful 设计的优雅微妙之处会阻止我看到一个好的解决方案,或者我是否试图将一个圆形钉子安装到一个方孔中(即 REST 不擅长拉大数据批次多个资源)?

【问题讨论】:

    标签: api rest


    【解决方案1】:

    我只是把它作为一个潜在的解决方案扔出去:

    从概念上讲,我将此查询的结果视为自身的资源 - 就像“orderReport”。

    将其视为自己的资源,API 的行为可能类似于:

    GET /orderReport/[some arbitrary date]
    

    然后您可以发回带有类似Location: /orderReport/[GUID] 的位置标头的201 Created(如果查询运行相对较快)。或者,如果查询需要一段时间才能运行(老实说,我不知道它是否在我的脑海中),你可以发回一个带有Location: /orderReport/[GUID]/status 位置标题的202 Accepted

    然后,您可以针对这些 URL 执行 GET 后续操作,以获取报告状态(200 OK,如果仍在处理且没有错误,201 Created,如果已完成,则位置标头指向报告 URL)或报告本身。

    除了满足用例要求所严格需要的数据之外,没有什么可以说报告数据也不能包含 HATEOAS,例如:

    {
      [
        {
           "order_num": 123,
           "order_uri": "/orders/123",
           "order_date": 2014-07-03, 
           "product_description": "widget", 
           "sales_rep_name": "Jane Doe",
           "sales_rep_uri": "/salesRep/34"
        },
        {
           "order_num": 456,
           "order_uri": "/orders/456",
           "order_date": 2014-07-04, 
           "product_description": "gadget", 
           "sales_rep_name": "Frank Smith",
           "sales_rep_uri": "/salesRep/53"
        }
      ]
    }
    

    【讨论】:

    • 这也是我解决问题的方法。请注意,GET 永远不应返回 201 或 202,因为这些代码表明正在创建资源。使用 POST 创建报告,使用 GET 检索状态/报告对象。您可以在 POST 中发送条件标头,以确保不会创建重复。
    • 好建议,谢谢 - 我会在我的初步设计中考虑到这一点。
    猜你喜欢
    • 2015-01-16
    • 1970-01-01
    • 2010-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-23
    • 1970-01-01
    相关资源
    最近更新 更多