MongoDB От одного до многих отношений

Я начал изучать MongoDB, и я в какой-то момент задал себе вопрос, как разрешить дизайн отношений "один ко многим" в MongoDB. Во время поиска я нашел много комментариев в других сообщениях/статьях вроде "вы думаете о реляционной". Хорошо я согласен. Будут такие случаи, как дублирование информации, которая не будет проблемой, например, пример КЛИЕНТОВ-ЗАКАЗОВ.

Но предположим, что у вас есть таблицы: ORDERS, у которого есть встроенная структура DETAIL с ПРОДУКТАМИ, которые клиент купил. Так что для чего-то нужно изменить имя продукта (или другой вид информации), который уже встроен в несколько порядков.

В конце концов, вы вынуждены выполнять привязку "один ко многим" в MongoDB (это означает, что помещение ObjectID в качестве ссылки на другую коллекцию), так что вы можете решить эту простую проблему, не так ли? Но каждый раз, когда я нашел статью/комментарий об этом, он говорит, что это будет ошибка производительности в Mongo. Его разочарование

Есть ли другой способ решить/спроектировать это без ошибки производительности в MongoDB?

Ответ 1

Проблема в том, что вы над нормализацией своих данных. Заказ определяется клиентом, который живет в определенном месте в данный момент времени, платит определенную цену, действительную на момент заказа (которая может сильно измениться в течение срока действия приложения и которую вы должны документировать в любом случае и несколько другие параметры, которые действительны только в определенный момент времени, поэтому для документирования заказа (предназначенного для каламбура) вам необходимо сохранить все данные за определенный промежуток времени. Позвольте мне привести пример:

{ _id: "order123456789",
  date: ISODate("2014-08-01T16:25:00.141Z"),
  customer: ObjectId("53fb38f0040980c9960ee270"),
  items:[ ObjectId("53fb3940040980c9960ee271"),
          ObjectId("53fb3940040980c9960ee272"),
          ObjectId("53fb3940040980c9960ee273")
         ],
 Total:400
 }

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

{
  _id: "order987654321",
  date: ISODate("2014-08-01T16:25:00.141Z"),
  customer: {
               userID: ObjectId("53fb3940040980c9960ee283"),
               recipientName: "Foo Bar"
               address: {
                          street: "742 Evergreen Terrace",
                          city: "Springfield",
                          state: null
                         }
            },
  items: [
    {count:1, productId:ObjectId("53fb3940040980c9960ee300"), price: 42.00 },
    {count:3, productId:ObjectId("53fb3940040980c9960ee301"), price: 0.99},
    {count:5, productId:ObjectId("53fb3940040980c9960ee302"), price: 199.00}
  ]
}

Благодаря этой модели данных и использованию агрегатных конвейеров у вас есть несколько преимуществ:

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

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

Ответ 2

От одного до многих отношений

В этом отношении существует много, много объектов или много объектов, которые сопоставляются с одним объектом. например.:  - В городе много людей, которые живут в этом городе. Скажем NYC имеет 8 миллионов человек.

Предположим, что приведенная ниже модель данных:

 
  //city
  {
  _id: 1,
  name: 'NYC',
  area: 30,
  people: [{
      _id: 1,
      name: 'name',
      gender: 'gender'
        .....
    },
    ....
    8 million people data inside this array
    ....
  ]
}

Это не сработает, потому что это будет ДЕЙСТВИТЕЛЬНО ОГРОМНЫМ. Попробуйте перевернуть голову.


 //people
 {
 _id: 1,
 name: 'John Doe',
 gender: gender,
 city: {
     _id: 1,
     name: 'NYC',
     area: '30'
       .....
   }
}

Теперь проблема с этим дизайном заключается в том, что, если в Нью-Йорке, очевидно, много людей, поэтому мы сделали много дублирования для данных города.

Вероятно, наилучшим способом моделирования этих данных является использование ссылки true.


 //people
 {
 _id: 1,
 name: 'John Doe',
 gender: gender,
 city: 'NYC'
}

//city
{
_id: 'NYC',
...
}

В этом случае коллекция people может быть связана с коллекцией city. Зная, что у нас нет ограничений внешнего ключа, мы должны быть последовательными. Таким образом, это отношение одного к большому. Он требует 2 коллекций. Для маленьких от одного до нескольких (что тоже одно для многих), таких как блог-сообщение для комментариев. Комментарии могут быть встроены в почтовые документы в виде массива.

Итак, если это действительно один для многих, 2 сборника лучше всего работают с привязкой. Но для одного к нескольким, как правило, достаточно одной коллекции.

Ответ 3

Поэтому я отдает должное @BaptisteL, чтобы ограничить мои предположения о MongoDB "Не забывайте, что mongodb - это база данных NoSQL, поэтому, если у вас есть много таких отношений в вашем db, вы, вероятно, должны пойти на SQL db, потому что mongodb всегда будет меньше преформировать с этой стороны". http://www.sarahmei.com/blog/2013/11/11/why-you-should-never-use-mongodb/