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/
Ответ 4
Этот вопрос более сложный. Я нашел статью с хорошим объяснением
http://blog.mongodb.org/post/87200945828/6-rules-of-thumb-for-mongodb-schema-design-part-1