RESTful API-обработка вложенных отношений


Предположим, я создаю API для обработки встреч. Прием состоит из врача, пациента и набора забот.

Если я хочу создать встречу, как должны выглядеть данные по почте? Обратите внимание, что только встреча будет создана с помощью этого запроса. Записи о враче, пациенте и заботах уже существуют в базе данных.

У меня есть 2 варианта:

Короткий

{
  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

Существуют ли какие-либо успокаивающие лучшие практики для такого рода случаев?

1 3

1 ответ:

На самом деле, вы столкнулись с проблемой отношений. OData предоставляет решение этой проблемы под названием "Свойства навигации". Возможно, это может дать вам некоторые подсказки на пути к исправлению этой проблемы. Вы можете посмотреть на эти ссылки для получения более подробной информации: http://www.odata.org/getting-started/basic-tutorial/ и http://www.odata.org/getting-started/advanced-tutorial/

На самом деле, здесь есть несколько вопросов:

  • конструируйте представление вы хотите иметь при получении назначения
  • проектирование представления для создания или обновления встречи
  • создайте представление для назначения (однократная мощность - "врач" и "пациент") / добавления и удаления (многократная мощность - "забота") ссылки на прием (например, врач)

Я думаю, что полное представление, которое вы даете в своем вопросе, соответствует тому, что вы ожидаете получить при получении встречи, т. е. данные отношений, как врач, пациент и заботы.

Такие подсказки не все необходимы, чтобы связать назначение с другими элементами, такими как врач и пациент. Важны только идентификаторы. Я думаю,что вы могли бы иметь другое представление для создания назначения. На этом уровне достаточно установки ссылки на элемент. Так что вы могли бы somethinhg так:

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 см. разделы "получение связанных сущностей", " создание связи между Сущности"и" удаление связи между сущностями". Это может дать подсказки для вашего представления.

Последняя часть вопроса связана с тем, как построить представление (например, для создания). Я не знаю точно, какую технологию вы используете, но в Java вы можете сделать что-то подобное appointment.doctor = selected_doctor и немного адаптировать сериализацию ваших объектов, чтобы создать что-то подобное doctor@metadata.ref: http://.../doctors/8 из экземпляра Doctor. Например, с Jackson2 , это называется custom сериализатор (см. Эту ссылку http://www.baeldung.com/jackson-custom-serialization например).

Надеюсь, это поможет вам, Тьерри