Rails 关于 jsonapi 或者说 RESTful API 的批量操作疑问

smartepsh · 2016年08月18日 · 最后由 smartepsh 回复于 2016年08月19日 · 4763 次阅读

最近在做基于 jsonapi 的设计, 本来的设想倒是挺不错,但是由于客户可能有工厂较大批量的存在,导致数据可能有批量操作的发生,尤其是在create操作上.

想问下大家,有没有什么较好的解决办法?

jsonapi 里的 post 操作一次仅允许提交一个数据. 我的想法是根据需要批量操作的动作创建单独的控制器,比如creates,然后定义typevalue等字段,我在控制器里解析操作.插入对应的表中.

但是感觉有点麻烦,不知道还有没有好的办法?

大量数据为何不试试如从 excel 中导入.

#1 楼 @wangping 这个我还真回答不上来....可能因为我只是单独做 api 的,而且数据在一定程度上属于实时获取,不能让厂商更改的,如果做成比如 execl 之类的文件再导入,厂商容易更改记录. 我这里主要想问的是,如果在一次请求中进行批量操作. 如果不处理批量的话,有多少条数据,就要发起多少次请求,压力会很大.

#2 楼 @smartepsh 一条数据记录参数多不?

我是这么做的: 写了一个名叫create_multiple的 action 参数格式是{model_name: [{ arrtibutes_hash }]} 然后使用 bulk_insert 进行批量插入

#3 楼 @wangping 不多,但是因为采用了 jsonapi 的格式,所以按规矩是没法一次传入多个对象的.

#4 楼 @night_7th 谢谢,在看 bulk_insert,但是这样的话,可能要打破 jsonapi 的规矩了.

#4 楼 @night_7th 当然看实际需求, 打破 jsonapi 也不是什么万万不能的事情😂

可以做,也不用打破规则。你可以建立一个 batch model 来处理,其中的一个 attribute 接受 array。如果 array 其中一个失败就全部回滚并报错。

#9 楼 @jicheng1014 你终于出现了...

post 操作一次仅允许提交一个数据是你们自己定义的吗?改成以数组的形式传递不就可以了

#12 楼 @geekontheway 是规范定义的,要么另辟蹊径,要么打破规则。

死抠 REST 的话,就如楼上几位讲的一样,把 batch model 也做为一个资源。我的观点是,REST 保持了接口的组合性,但是对于特定的要求还是 RPC 更好。

这样想一下,batch create 的时候如何控制超时?如果有冲突的数据需要先处理哪一个?如果出错了如何让用户知道是哪个数据出错?

JSON API 原本是有一个 bulk extension 的,实际上 JSON API 是有一个扩展系统的设计的,而 bulk 是其中之一:https://github.com/json-api/json-api/blob/9c7a03dbc37f80f6ca81b16d444c960e96dd7a57/extensions/bulk/index.md

当然,标准对其做了规范是一方面,具体的实现有没有做那就要单说了。

然而这个扩展系统一直以来都是试验性质的,并且目前已经被 deprecated 了。照官方的说法,一个新的扩展系统正在开发中,希望它能长久稳定吧。

#14 楼 @nouse 是的,还在考虑中,不过你您后面提的问题, 具体情况具体分析,还是可以解决的.如果放在我这里的话:

  1. 整体作为事务,超时全体退回.
  2. 数据采集过程中,每添加一条信息,就与本地存储内的数据对比,具体保留哪一个,看情况. 上传过程中,同样以事务处理, 检查与数据库中的冲突,并根据情况保留.
  3. 针对每一个资源返回错误信息. 如果有错误,返回的是一个错误数组,jsonapi 靠 id 和 type 可以定位资源,同样可以定位错误.(前提是他要支持😂 )

总之,视情况而定吧.我先看看楼上的一个方法,感觉可行. 谢谢您的回复.😄

#15 楼 @nightire 看着真是诱人...虽然没定义服务器必须响应什么...问题是 deprecated...看来暂时好点的办法还是单独创建一个复合资源吧,幸好需要批量的场景并不多.

#8 楼 @billy 还有个问题麻烦问一下,新建操作可以这样子操作,那删除呢? 因为如果使用 delete 方法进行删除,那么应该在请求地址上就先会有问题出现,因为 delete 方法的地址应该是/model/id,而不能是/models. 那一般是不是还是要利用POST做批量删除操作?

我是想着针对批量操作新建 batch model,比如batchCreateModel,batchDeleteModel,都仅有create方法,用 POST 把参数在 jsonapi 的primary data里以数组的方式体现出来进行操作. 这种方法可行嘛?

@smartepsh 如果是删除其他的 model, 你可以把它当作一个新增的 batch,都是 POST。

#19 楼 @billy 对,我意思就是没办法用 DELETE 方法执行了.那大概就先这么做啦,谢谢回复!

  • 定义 attributes
params :actor do
  requires :name,      type: String
  requires :character, type: String
  requires :movie_id,  type: Integer
end
  • 单或多
params do
  optional :actor, type: Hash do
    use :actor
  end

  optional :actors, type: Array[Hash] do
    use :actor
  end

  at_least_one_of :actor, :actors
end
post '/' do
  @actors = unless params[:actors].blank?
    Actor.create(params[:actors])
  else
    [Actor.create(params[:actor])]
  end
end
  • rails 支持批量创建:
Model.create([
  {name: "John Doe", character: "The Hobbit", movie_id: 1}, 
  {name: "Christian Bale", character: "Batman", movie_id: 2}
])

#21 楼 @mimosa 谢谢回复,但是这个好像对 jsonapi 没有效果的. 传入的数据不是单纯的对象的集合.

需要 登录 后方可回复, 如果你还没有账号请 注册新账号