API设计:缓存“部分”嵌套对象

时间:2016-08-08 03:52:53

标签: rest reactjs data-structures redux api-design

我们假设我们的学校有一些数据,包括姓名和学生名单,以及有一些数据的学生,包括他们注册的课程和他们学校的参考。在客户端:

  • 我想显示一个显示学校信息的屏幕,其中包括所有学生的名单。
  • 我想显示一个显示学生信息的屏幕,包括他们学校的名称和他们正在学习的课程名称。
  • 我想缓存此信息,以便我可以显示相同的屏幕,而无需等待新的提取。我应该能够从学校到学生再回到学校而不再去学校。
  • 我希望每个屏幕只显示一次。从学校页面到学生页面可以单独获取,但我应该能够在一次学习中向学校显示学生姓名的完整列表。
  • 我希望避免重复数据,这样如果学校名称发生变化,只需一次更新学校,就可以在学校页面和学生页面上显示正确的名称。

是否有一个很好的方法来完成所有这些,或者是否必须解除一些限制?

第一种方法是使用这样的API:

GET /school/1

{
    id: 1,
    name: "Jefferson High",
    students: [
        {
             id: 1
             name: "Joel Kim"
        },
        {
             id: 2,
             name: "Chris Green"
        }
        ...
    ]
}


GET /student/1

{
    id: 1,
    name: "Joel Kim",
    school: {
        id: 1,
        name: "Jefferson High"
    }
    courses: [
        {
             id: 3
             name: "Algebra 1"
        },
        {
             id: 5,
             name: "World History"
        }
        ...
    ]
}

这种方法的一个优点是,对于每个屏幕,我们只需要进行一次获取。在客户端,我们可以规范学校和学生,以便他们互相引用ID,然后将对象存储在不同的数据存储中。但是,嵌套在student内的school对象并不是一个完整的对象 - 它不包含嵌套的课程,也不包含回学校的参考。同样,school内的student对象也没有所有参加学生的列表。在数据存储中存储对象的部分表示将导致客户端上的一堆复杂逻辑。

我们可以为学校和学生存储嵌套的部分对象,而不是规范化这些对象。然而,这意味着数据重复 - Jefferson High的每个学生都会将学校的名称嵌套。如果在为特定学生取得学校名称之前更改了学校名称,那么我们会为该学生显示正确的学校名称,但在其他地方显示错误的名称,包括学校详细信息"页。

另一种方法可能是设计API以仅返回嵌套对象的ID:

GET /school/1

{
    id: 1,
    name: "Jefferson High",
    students: [1, 2]
}


GET /student/1

{
    id: 1,
    name: "Joel Kim",
    school: 1,
    courses: [3, 5]
}

我们总是"完成"具有所有引用的对象的表示,因此将此信息存储在数据存储客户端中非常容易。但是,这需要多次提取才能显示每个屏幕。为了显示学生的信息,我们必须取得学生,然后取回他们的学校,以及他们的课程。

是否有一种更智能的方法可以让我们只缓存每个对象的一个​​副本,并防止多个提取显示基本屏幕?

1 个答案:

答案 0 :(得分:3)

您可能会混合两个概念:存储表示。你可以回馈一个非标准化的表示(你建议的第一个选项)没有也存储那些" partial"数据库中的对象。

所以我建议尝试返回非规范化的表示,但存储它们是规范化的(如果你使用的是关系数据库)。

此外,还有一个改进建议:您可能希望在表示中使用正确的URI而不是ID。您可能希望客户知道"其中"为了获得该对象,因此更容易提供URI。否则,客户端需要弄清楚如何从Id中生成URI,并且通常最终在客户端中进行硬编码,这在REST中是禁止的。