如何使用RESTAPI实现复杂查询?

如何使用RESTAPI实现复杂查询?,api,rest,ember-data,Api,Rest,Ember Data,我正在使用余烬数据构建一个余烬JS应用程序 我的应用程序中的某些功能需要相当复杂的查询 例如,假设我有三个实体——学生、教师和班级。如果我想得到1993年以前出生的所有参加X老师授课的学生的名单,我怎么能用RESTful api做到这一点?在纯SQL中这很容易,但我不确定在API中实现这一点的最佳实践 我是否需要在我的基本RESTAPI旁边构建一个自定义端点 所以我仍然有: GET /students (which returns all the students) GET /students/

我正在使用余烬数据构建一个余烬JS应用程序

我的应用程序中的某些功能需要相当复杂的查询

例如,假设我有三个实体——学生、教师和班级。如果我想得到1993年以前出生的所有参加X老师授课的学生的名单,我怎么能用RESTful api做到这一点?在纯SQL中这很容易,但我不确定在API中实现这一点的最佳实践

我是否需要在我的基本RESTAPI旁边构建一个自定义端点

所以我仍然有:

GET /students (which returns all the students)
GET /students/{id} (which returns a specific student)
etc
然后为我的“自定义”查询实现以下功能:

GET /students/custom/born_before/{date}/taught_by/{teacher_id}
或者有没有更标准化的方法来实现这一点?

您可以改变您的

GET /students/custom/born_before/{date}/taught_by/{teacher_id}
进入

这只是一个选项:您可以使用提供的字段填充模型实例,并使用它们进行查询。字段越少,搜索范围越广,显示的结果越多


例如,这就是一种方法。

一种选择是在学生身上设置一个搜索端点,您可以发布到该端点

所以你可能有:

POST /students/filter
您要发布的筛选器对象看起来类似于:

{ BornBefore:1993, TaughtBy:123 }
我还看到了一个选项,API没有发布,而是使用了一个过滤器,然后使用了一个查询字符串

我自己更喜欢第一个。特别是如果它可能是一个长时间运行的过程,因为您的POST可能会返回一个ID和/或一个指向客户端用于获取状态更新和结果的API调用的
rel
链接

因此,您将
发布/Students/filter
,它将以
/Students/filter/123
的rel回复,您的客户机将在
/Students/filter/123
上定期执行
获取
,直到获得结果对象。当然,对于简单、简短的查询,您可以立即返回结果。但是如果要花一两秒钟以上的时间,你可以走这条路


有一些关于构建ReSTful API的好信息。

我不喜欢使用POST来“获取”信息,我认为这不是ReSTful。我更新了我的答案,以说明在某些情况下为什么要发布POST。本质上,您是在发布服务器运行的搜索对象,然后稍后再获取结果。很像你将一个图像发布到服务器上,然后再检索它。这更像是
/students/filters
,因为有很多。无论如何,对于一般用例来说,这不是一个最佳的解决方案。必须发出两个请求才能执行简单的搜索&将其存储在后端没有什么意义。使用GET的最大问题是,代理将使用它们自己的规则缓存它们,尽管您可能发送任何头。POST/PUT从不缓存。尽管这种情况很少见,但在与用户打交道时(尤其是在业务环境中)仍然需要考虑。这是一种更标准、更实用的解决方案,结果可以缓存(与
POST
的解决方案相反)。@Aurélien这也可能是不幸的,尤其是如果你不想缓存。我唯一的问题是,对于复杂的查询和过滤器,这样做真的很难看。@Rahly首先,您没有义务实现缓存。其次,缓存并不意味着获取过时的数据(例如,
ETag
就是一种很好的处理方法)。如果实现正确,这只意味着你不必再计算你已经计算过的东西。@Aurélien不,这就是问题所在,其他人可以在你和你的用户控制之外实现缓存。我在实际的代理环境中见过,代理服务器忽略所有缓存头并执行自己的“规则”。POST是常用的非缓存方法
{ BornBefore:1993, TaughtBy:123 }