Должен ли я денормализировать или запускать несколько запросов в DocumentDb?

Я изучаю моделирование данных в DocumentDb. Вот где мне нужен совет

Пожалуйста, посмотрите, как выглядят мои документы внизу.

Здесь я могу использовать два подхода как с плюсами, так и с минусами.

Сценарий 1:

Если я сохраняю денормализованные данные (см. мои документы ниже), сохраняя информацию о членах проектной группы, т. е. имя, фамилию, адрес электронной почты и т. д., в том же документе, что и проект, я могу получить нужную мне информацию в одном запросе, НО когда Джейн Доу выходит замуж и меняет фамилию, мне придется обновить множество документов в коллекции проектов. Я также должен был бы быть чрезвычайно осторожным, чтобы убедиться, что все коллекции с документами, содержащими информацию о сотрудниках, также обновляются. Если, например, я обновлю имя Джейн Доу в коллекции Projects, но забуду обновить коллекцию TimeSheets, у меня будут проблемы!

Сценарий 2:

Если я немного нормализую данные и оставлю в документах проекта только EmployeeId, я смогу запускать три запроса всякий раз, когда захочу получить список проектов:

  • Запрос 1 возвращает список проектов
  • Запрос 2 даст мне EmployeeId всех членов команды проекта, которые появляются в первом запросе.
  • Запрос 3 для информации о сотруднике, т. е. имени, фамилии, электронной почты и т. д. Я бы использовал результат запроса 2 для запуска этого

Затем я могу объединить все данные в своем приложении.

Проблема здесь в том, что DocumentDb теперь имеет много ограничений. Я могу читать сотни проектов с сотнями сотрудников в проектных командах. Похоже, нет эффективного способа получить всю информацию о сотрудниках, чьи идентификаторы появляются в моем втором запросе. Опять же, пожалуйста, имейте в виду, что мне может понадобиться получить здесь информацию о сотнях сотрудников. Если следующий SQL-запрос — это то, что я бы использовал для данных о сотрудниках, мне, возможно, придется выполнить один и тот же запрос несколько раз, чтобы получить всю необходимую мне информацию, потому что я не думаю, что могу иметь сотни операторов ИЛИ:

SELECT e.Id, e.firstName, e.lastName, e.emailAddress
FROM Employees e
WHERE e.Id = 1111 OR e.Id = 2222

Я понимаю, что DocumentDb все еще находится в предварительной версии, и некоторые из этих ограничений будут исправлены. С учетом сказанного, как мне подойти к этой проблеме? Как я могу эффективно хранить/управлять и извлекать все необходимые данные проекта, включая информацию о команде проекта? Является ли Сценарий 1 лучшим решением или Сценарий 2, или есть лучший третий вариант?

Вот как выглядят мои документы. Во-первых, проектный документ:

{
   id: 789,
   projectName: "My first project",
   startDate: "9/6/2014",
   projectTeam: [
      { id: 1111, firstName: "John", lastName: "Smith", position: "Sr. Engineer" },
      { id: 2222, firstName: "Jane", lastName: "Doe", position: "Project Manager" }
   ]
}

А вот два документа сотрудников, которые находятся в коллекции Employees:

{
   id: 1111,
   firstName: "John",
   lastName: "Smith",
   dateOfBirth: "1/1/1967',
   emailAddresses: [
      { email: "[email protected]", isPrimary: "true" },
      { email: "[email protected]", isPrimary: "false" }
   ]
},
{
   id: 2222,
   firstName: "Jane",
   lastName: "Doe",
   dateOfBirth: "3/8/1975',
   emailAddresses: [
      { email: "[email protected]", isPrimary: "true" }
   ]
}

person Sam    schedule 07.09.2014    source источник
comment
Почему вы добавили mongodb здесь?   -  person Salvador Dali    schedule 07.09.2014
comment
Потому что в конечном счете речь идет о моделировании данных в базах данных документов, и я хочу посмотреть, есть ли подход, которого я еще не видел.   -  person Sam    schedule 07.09.2014
comment
Я размышляю о том же самом. Есть ли у вас какие-либо комментарии/понимание вашего опыта с тех пор? Мне интересно либо нормализовать и читать пользователей в контексте (например: связанный с проектом в вашем случае) и ссылаться на изменчивую информацию там (более 1 запроса), либо денорнализовать и, возможно, иметь функцию обновления/обновления пользовательских данных чтобы админы обновляли имена при необходимости? (Я стараюсь держаться подальше от хранимой процедуры, если могу)   -  person Mark Redman    schedule 23.01.2018
comment
Много уроков, извлеченных с тех пор, как я опубликовал этот вопрос. Два основных вывода: если вы собираетесь использовать базу данных NoSQL, вам нужно привыкнуть к идее денормализации. В противном случае вы не воспользуетесь тем преимуществом, которое предлагают базы данных NoSQL, а именно скоростью и масштабируемостью. Второй не менее важный урок заключается в том, что вам нужна хорошая стратегия обеспечения целостности данных, потому что база данных NoSQL не делает этого за вас. Поэтому вам нужно хорошее серверное рабочее приложение, такое как функция Azure или веб-задания, чтобы справиться с этим. И последнее, но не менее важное: не уклоняйтесь от хранимых процедур. Они супер полезные.   -  person Sam    schedule 23.01.2018
comment
Что бы это ни стоило, вот видео, которое я снял о своем путешествии от реляционных систем к NoSQL. Вот он: youtu.be/15-tb6u4RGM Удачи!   -  person Sam    schedule 23.01.2018


Ответы (1)


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

Сценарий 1). Если вы денормализуете свою модель данных (связываете данные о проектах и ​​сотрудниках вместе) — вам может потребоваться обновлять многие проекты при обновлении< /em> сотрудник.

Сценарий 2). Если вы нормализуете свою модель данных (разделите проекты и данные о сотрудниках), вам придется запрашивать проекты для получения идентификаторов сотрудников, а затем запрашивать сотрудников, если вы хотите получить список сотрудников, принадлежащих к проекту.

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

Обратите внимание, что вы можете избежать многократного обращения между вашим приложением и базой данных, используя процедуры хранения DocumentDB (запросы будут выполняться на стороне сервера DocumentDB).

Вот пример процедуры хранения для получения сотрудников, принадлежащих определенному идентификатору проекта:

function(projectId) {
  /* the context method can be accessed inside stored procedures and triggers*/
  var context = getContext();
  /* access all database operations - CRUD, query against documents in the current collection */
  var collection = context.getCollection();
  /* access HTTP response body and headers from the procedure */
  var response = context.getResponse();

  /* Callback for processing query on projectId */
  var projectHandler = function(documents) {
    var i;
    for (i = 0; i < documents[0].projectTeam.length; i++) {
      // Query for the Employees
      queryOnId(documents[0].projectTeam[i].id, employeeHandler);
    }
  };

  /* Callback for processing query on employeeId */
  var employeeHandler = function(documents) {
    response.setBody(response.getBody() + JSON.stringify(documents[0]));
  };

  /* Query on a single id and call back */
  var queryOnId = function(id, callbackHandler) {
    collection.queryDocuments(collection.getSelfLink(),
      'SELECT * FROM c WHERE c.id = \"' + id + '\"', {},
      function(err, documents) {
        if (err) {
          throw new Error('Error' + err.message);
        }
        if (documents.length < 1) {
          throw 'Unable to find id';
        }
        callbackHandler(documents);
      }
    );
  };

  // Query on the projectId
  queryOnId(projectId, projectHandler);
}

Даже несмотря на то, что DocumentDB поддерживает ограниченные операторы OR во время предварительной версии, вы все равно можете получить относительно хорошую производительность, разделив поиск employeeId на набор асинхронных запросов на стороне сервера.

person Andrew Liu    schedule 08.09.2014
comment
Благодарю за ваш ответ. Я чувствую, что последний подход также лучше. Мне просто нужно освоить хранимые процедуры JS в DocumentDB. Еще раз спасибо. Я тоже ценю пример кода. - person Sam; 09.09.2014