RESTful API - 处理嵌套关系

时间:2015-03-21 09:47:55

标签: api rest nested relationship restful-architecture

假设我正在构建一个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'
    }
  ]
}

较短的一个感觉更干净,因为我们没有发送无用的数据,如姓名和地址等。但第二个感觉在我的前端代码中更自然/语义。

例如在我的申请中,我只需要这样做:

appointment.doctor = selected_doctor
// Instead of doing
appointment.doctor_id = selected_doctor.id

对于这种情况,是否有任何RESTful最佳做法?

1 个答案:

答案 0 :(得分:1)

事实上,你正面临着关系问题。 OData为这个问题提供了解决方案,称为"导航属性"。也许这可以给你一些解决方法来解决这个问题。您可以查看这些链接以获取更多详细信息:http://www.odata.org/getting-started/basic-tutorial/http://www.odata.org/getting-started/advanced-tutorial/

事实上,这里有几个问题:

  • 设计预约时想要的表示
  • 设计表示以创建或更新约会
  • 设计要分配的表示(单基数 - "医生"和#34;患者")/添加和删除(多基数 - "关心)指向预约的链接(例如医生)

我认为您在问题中提供的完整陈述与预约时的预期相符,即预约数据包括医生,患者和护理等关系数据。

这些提示并不是将约会与医生和病人等其他因素联系起来的必要条件。只有标识符很重要。我认为您可以为约会创建提供不同的表示形式。在此级别设置对元素的引用就足够了。所以你可以有这样的想法:

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 ]
}

以同样的方式,您可以定义其他资源,以便在创建约会后更新这些链接,而无需发送所有内容。我们可以想象这样的事情:

  • 单基数

    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'
          }
       ]
     }
    

    }

  • 使用链接/参考文献进行parial

    {
      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对应。

您可以查看此链接:http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/entity-relations-in-odata-v4。请参阅&#34;获取相关实体&#34;,&#34;创建实体之间的关系&#34;和&#34;删除实体之间的关系&#34;。它可以为您的代表提供提示。

问题的最后一部分与构建表示的方式有关(例如,用于创建)。我不确切地知道您使用的技术,但在Java中,您可以执行类似appointment.doctor = selected_doctor的操作,并根据对象的序列化进行调整,以便从一个实例中创建类似doctor@metadata.ref: http://.../doctors/8的内容。医生。例如,使用Jackson2,它就称为自定义序列化程序(例如,请参阅此链接http://www.baeldung.com/jackson-custom-serialization)。

希望它可以帮到你, 亨利