REST:处理计算和相关资源属性

时间:2013-12-28 18:40:39

标签: api mongodb rest mongoose

假设我有一个类似Wordpress的博客系统,其资源包括用户,帖子和评论资源。这些资源中的每一个都作为单独的集合存储在MongoDB数据库中,并且它们通过ObjectID值字段相互关联。具体来说:帖子的author字段包含其相关用户资源的ObjectID,评论的相关用户有author字段,帖子的ObjectID有relatedPost字段评论适用于此。

显然,在许多情况下,单独检索这些资源效率低下。一个示例是显示特定的Post资源客户端:理想情况下,该帖子的作者姓名应与帖子标题和正文一起显示,但Post文档本身仅包含相关用户文档的ObjectID。

简单的解决方案是在服务器端检索这些相关属性,并将其他数据发送到客户端。虽然对于像我正在描述的博客那样简单的东西来说这是一个很好的解决方案,但它为更复杂的系统提出了一些问题。具体做法是:

  • 如果GET /api/posts/#{postID}返回的JSON对象的属性不是给定Post文档的真正属性,我该如何通知客户?
  • 作为第一个问题的扩展:如何通知客户端尝试使用POST更新该文档的给定字段到相同的URI不会实际更新资源?
  • GET /api/posts/#{postID}更适合仅返回该文档中真正存在的属性,使用/api/posts/#{postID}/withauthor之类的辅助URI返回文档以及相关信息吗?

更具体地说,假设这些资源是由以下Mongoose.js样式模式定义的:

User: {
  _id: ObjectID,
  username: String,
  name: {
    first: String,
    last: String
  }
}

Post: {
  _id: ObjectID,
  author: ObjectID,
  title: String,
  body: String,
  timestamp: Date
}

Comment: {
  _id: ObjectID,
  author: ObjectID,
  relatedPost: ObjectID,
  title: String,
  body: String,
  timestamp: Date
}

我想要一个GET能力资源,它返回一个Post文档的完整表示以及相关作者的名字和姓氏,如下所示:

request: GET /api/posts/529635f828ab08e00d000084

response: {
  _id: "529635f828ab08e00d000084",
  title: "A Post",
  body: "It turns out I have very little to say.",
  author: {
    _id: "928495a321cf09c11d198001",
    name: {
      first: "John",
      last: "Smith"
    }
  }

我不想让客户认为将JSON更新author.name.firstPOST到同一个URI会对文档的author属性产生任何影响在后端。只有author._id的更新才能更改文档的作者。对此有一个共同的“RESTful”方法吗?

我知道这里没有一个正确答案,我之前描述的简单方法将适用于这个特定问题。但我很好奇其他人如何在更复杂的API中解决这个问题。

(注意:我很可能会过度思考这个问题。)

1 个答案:

答案 0 :(得分:2)

这是设计RESTful服务时非常常见的问题。我发现处理这个问题的最好方法是正确记录您的REST服务(甚至可以为客户提供一个游乐场环境来试用api)。这是我将如何处理您的用例。

我将对给定的blog_post发出GET请求,该请求只返回blog_post实体

  

GET / api / posts / abcd1234

返回带有作者ID的基本blog_post。

现在,我将对此相同的GET请求进行更改:

  

GET / api / posts / abcd1234?comments = true& authors = true& startIndex = 0& offset = 10& sortDirection = Ascending& sortBy = comment_date

以上api将返回带有作者的帖子和带有作者的评论列表以及与分页等相关的其他过滤器。客户端可以在此api过滤器上使用他们喜欢的任何排列组合,并根据过滤器,您返回数据回来了,

  

blog_post:{

     

这里你正常的blog_post字段......

     

这里的完整作者对象......

     

评论:[{

     

评论列表(每个评论和应用过滤器的作者)在这里......

     

}]

     

}

这也将为同一blog_post上的其他请求维护您的RESTful方法。例如,更新blog_post的作者

  

POST / api / posts / abcd1234

仍将仅更新blog_post中的authorId,因为您将记录此POST请求的方式只是让客户知道您在这里唯一期望的是具有id,title,body和authorId以及其他所有字段的blog_post对象

将丢弃/忽略他们作为blog_post请求的一部分发送给您的信息。

客户端如何使用REST服务,在很大程度上取决于您对REST服务的记录情况。