RESTful API - 处理嵌套关系
RESTful API - Handling nested relations
假设我正在构建一个 API 来处理约会。一个预约包括一名医生、一名患者和一组护理。
如果我想创建约会,POST 数据应该是什么样的?请注意,此查询只会创建约会。数据库中已存在医生、患者和护理条目。
我有两个选择:
短的
{
doctor_id: 8,
patient_id: 4,
cares_ids:
[1,7]
}
较长的那个
{
doctor: {
id: 8,
name: 'Dr James Brown',
phone: '107-102-304',
address: '16th avenue'
},
patient: {
id: 4,
name: 'Mr Elvis',
pathology: 'Blah Blah.'
},
cares:
[
{
id: 1,
name: 'Dental cares'
},
{
id: 7,
name: 'Back pain'
}
]
}
短的感觉更干净,因为我们没有发送无用的数据,如姓名和地址等。但第二个在我的前端代码中感觉更 natural/semantic。
例如在我的应用程序中,我只需要做:
appointment.doctor = selected_doctor
// Instead of doing
appointment.doctor_id = selected_doctor.id
对于这种情况,是否有任何RESTful最佳实践?
其实你面临的是关系问题。 OData 提供了解决此问题的方法,称为 "navigation properties"。也许这可以为您提供一些解决此问题的提示。您可以查看这些 links 了解更多详情:http://www.odata.org/getting-started/basic-tutorial/ and http://www.odata.org/getting-started/advanced-tutorial/
其实这里有几个问题:
- 设计你想要在预约时拥有的表现形式
- 设计表示以创建或更新约会
- 设计表示以分配(单基数 - "doctor" 和 "patient")/添加和删除(多基数 - “关心)link 到约会(例如医生)
我认为你在问题中给出的完整表示对应于你在预约时所期望的,即预约数据包括医生、患者和护理等关系的数据。
这些提示对于 link 预约医生和病人等其他元素并非都是必需的。只有标识符很重要。我认为您可以对约会创建有不同的表示。在此级别设置对元素的引用就足够了。所以你可以有这样的东西:
POST /appointments
{
doctor-ref: http://.../doctors/8,
patient-ref: http://.../patients/4,
cares-ref: [ http://.../cares/1, http://.../cares/7 ]
}
或
POST /appointments
{
doctor@metadata.ref: http://.../doctors/8,
patient@metadata.ref: http://.../patients/4,
cares@metadata.ref: [ http://.../cares/1, http://.../cares/7 ]
}
以同样的方式,您可以定义额外的资源,以便能够在创建约会后更新这些 link,而无需发送所有内容。我们可以想象这样的事情:
单基数
PUT /appointments/<appointmentid>/doctor
{ doctor@metadata.ref: http://.../doctors/8 }
多基数
POST /appointments/<appointmentid>/cares
{ metadata.ref: http://.../cares/8 }
DELETE appointments/<appointmentid>/cares
{ metadata.ref: http://.../cares/8 }
您会注意到,您也可以选择不检索某个约会的所有约会数据(如果您对此感兴趣)。以下是您可能拥有的不同表示形式:
完成
{
doctor: {
id: 8,
name: 'Dr James Brown',
phone: '107-102-304',
address: '16th avenue'
},
patient: {
id: 4,
name: 'Mr Elvis',
pathology: 'Blah Blah.'
},
cares:
[
{
id: 1,
name: 'Dental cares'
},
{
id: 7,
name: 'Back pain'
}
]
}
}
与links/参考文献
并列
{
doctor@metadata.ref: http://.../doctors/8,
patient: {
id: 4,
name: 'Mr Elvis',
pathology: 'Blah Blah.'
},
cares@metadata.ref: [ http://.../cares/1, http://.../cares/7 ]
}
或
{
doctor@metadata.ref: http://.../doctors/8,
patient: {
id: 4,
name: 'Mr Elvis',
pathology: 'Blah Blah.'
},
cares:
[
{
id: 1,
name: 'Dental cares'
},
{
id: 7,
name: 'Back pain'
}
]
}
}
此功能在 OData 中对应于查询参数 $expand
。
你可以看看这个 link:http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/entity-relations-in-odata-v4。请参阅 "Getting Related Entities"、"Creating a Relationship Between Entities" 和 "Deleting a Relationship Between Entities" 部分。它可以为您的表示提供提示。
问题的最后一部分与构建表示的方式有关(例如创建)。我不确切知道你使用的技术,但在 Java 中,你可以做类似的事情 appointment.doctor = selected_doctor
并稍微调整你的对象的序列化以创建类似的东西 doctor@metadata.ref: http://.../doctors/8
医生的例子。例如以 Jackson2, it's called custom serializer (see this link http://www.baeldung.com/jackson-custom-serialization 为例)。
希望对你有帮助,
蒂埃里
假设我正在构建一个 API 来处理约会。一个预约包括一名医生、一名患者和一组护理。
如果我想创建约会,POST 数据应该是什么样的?请注意,此查询只会创建约会。数据库中已存在医生、患者和护理条目。
我有两个选择:
短的
{
doctor_id: 8,
patient_id: 4,
cares_ids:
[1,7]
}
较长的那个
{
doctor: {
id: 8,
name: 'Dr James Brown',
phone: '107-102-304',
address: '16th avenue'
},
patient: {
id: 4,
name: 'Mr Elvis',
pathology: 'Blah Blah.'
},
cares:
[
{
id: 1,
name: 'Dental cares'
},
{
id: 7,
name: 'Back pain'
}
]
}
短的感觉更干净,因为我们没有发送无用的数据,如姓名和地址等。但第二个在我的前端代码中感觉更 natural/semantic。
例如在我的应用程序中,我只需要做:
appointment.doctor = selected_doctor
// Instead of doing
appointment.doctor_id = selected_doctor.id
对于这种情况,是否有任何RESTful最佳实践?
其实你面临的是关系问题。 OData 提供了解决此问题的方法,称为 "navigation properties"。也许这可以为您提供一些解决此问题的提示。您可以查看这些 links 了解更多详情:http://www.odata.org/getting-started/basic-tutorial/ and http://www.odata.org/getting-started/advanced-tutorial/
其实这里有几个问题:
- 设计你想要在预约时拥有的表现形式
- 设计表示以创建或更新约会
- 设计表示以分配(单基数 - "doctor" 和 "patient")/添加和删除(多基数 - “关心)link 到约会(例如医生)
我认为你在问题中给出的完整表示对应于你在预约时所期望的,即预约数据包括医生、患者和护理等关系的数据。
这些提示对于 link 预约医生和病人等其他元素并非都是必需的。只有标识符很重要。我认为您可以对约会创建有不同的表示。在此级别设置对元素的引用就足够了。所以你可以有这样的东西:
POST /appointments
{
doctor-ref: http://.../doctors/8,
patient-ref: http://.../patients/4,
cares-ref: [ http://.../cares/1, http://.../cares/7 ]
}
或
POST /appointments
{
doctor@metadata.ref: http://.../doctors/8,
patient@metadata.ref: http://.../patients/4,
cares@metadata.ref: [ http://.../cares/1, http://.../cares/7 ]
}
以同样的方式,您可以定义额外的资源,以便能够在创建约会后更新这些 link,而无需发送所有内容。我们可以想象这样的事情:
单基数
PUT /appointments/<appointmentid>/doctor { doctor@metadata.ref: http://.../doctors/8 }
多基数
POST /appointments/<appointmentid>/cares { metadata.ref: http://.../cares/8 } DELETE appointments/<appointmentid>/cares { metadata.ref: http://.../cares/8 }
您会注意到,您也可以选择不检索某个约会的所有约会数据(如果您对此感兴趣)。以下是您可能拥有的不同表示形式:
完成
{ doctor: { id: 8, name: 'Dr James Brown', phone: '107-102-304', address: '16th avenue' }, patient: { id: 4, name: 'Mr Elvis', pathology: 'Blah Blah.' }, cares: [ { id: 1, name: 'Dental cares' }, { id: 7, name: 'Back pain' } ] }
}
与links/参考文献
并列{ doctor@metadata.ref: http://.../doctors/8, patient: { id: 4, name: 'Mr Elvis', pathology: 'Blah Blah.' }, cares@metadata.ref: [ http://.../cares/1, http://.../cares/7 ] }
或
{ doctor@metadata.ref: http://.../doctors/8, patient: { id: 4, name: 'Mr Elvis', pathology: 'Blah Blah.' }, cares: [ { id: 1, name: 'Dental cares' }, { id: 7, name: 'Back pain' } ] }
}
此功能在 OData 中对应于查询参数 $expand
。
你可以看看这个 link:http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/entity-relations-in-odata-v4。请参阅 "Getting Related Entities"、"Creating a Relationship Between Entities" 和 "Deleting a Relationship Between Entities" 部分。它可以为您的表示提供提示。
问题的最后一部分与构建表示的方式有关(例如创建)。我不确切知道你使用的技术,但在 Java 中,你可以做类似的事情 appointment.doctor = selected_doctor
并稍微调整你的对象的序列化以创建类似的东西 doctor@metadata.ref: http://.../doctors/8
医生的例子。例如以 Jackson2, it's called custom serializer (see this link http://www.baeldung.com/jackson-custom-serialization 为例)。
希望对你有帮助, 蒂埃里