Я новичок в MongoDB - из реляционной базы данных. Я хочу разработать структуру вопроса с некоторыми комментариями, но я не знаю, какое отношение использовать для комментариев: embed
или reference
?
Вопрос с некоторыми комментариями, например stackoverflow , будет иметь такую структуру:
Question
title = 'aaa'
content = bbb'
comments = ???
Сначала я хочу использовать встроенные комментарии (я думаю, что embed
рекомендуется в MongoDB), например:
Question
title = 'aaa'
content = 'bbb'
comments = [ { content = 'xxx', createdAt = 'yyy'},
{ content = 'xxx', createdAt = 'yyy'},
{ content = 'xxx', createdAt = 'yyy'} ]
Это понятно, но меня беспокоит этот случай: если я хочу отредактировать указанный комментарий, как мне получить его содержание и вопрос? Нет ни того, _id
чтобы позволить мне найти его, ни question_ref
позволить мне найти его вопрос. (Я настолько новичок, что не знаю, есть ли способ сделать это без _id
и question_ref
.)
Должен ли я использовать ref
нет embed
? Тогда я должен создать новую коллекцию для комментариев?
Ответы:
Это больше искусство, чем наука. Монго Документация по Schemas является хорошим справочником, но здесь есть некоторые вещи , чтобы рассмотреть следующие вопросы:
Положите как можно больше
Радость базы данных документов заключается в том, что она исключает множество объединений. Ваш первый инстинкт должен состоять в том, чтобы разместить как можно больше в одном документе. Поскольку документы MongoDB имеют структуру и поскольку вы можете эффективно выполнять запросы внутри этой структуры (это означает, что вы можете взять ту часть документа, которая вам нужна, поэтому размер документа не должен вас сильно беспокоить), нет необходимости в немедленной нормализации данных, таких как вы бы в SQL. В частности, любые данные, которые не являются полезными, кроме его родительского документа, должны быть частью одного и того же документа.
Отдельные данные, на которые можно ссылаться из нескольких мест, в свою собственную коллекцию.
Это не столько проблема «пространства хранения», сколько проблема «согласованности данных». Если многие записи ссылаются на одни и те же данные, более эффективно и менее подвержено ошибкам обновлять одну запись и хранить ссылки на нее в других местах.
Размер документа
MongoDB накладывает ограничение на размер в 4 МБ (16 МБ с 1,8) для одного документа. В мире ГБ данных это звучит мало, но это также 30 тысяч твитов или 250 типичных ответов переполнения стека или 20 мерцающих фотографий. С другой стороны, это гораздо больше информации, чем можно было бы представить за один раз на типичной веб-странице. Сначала подумайте, что облегчит ваши запросы. Во многих случаях забота о размерах документов будет преждевременной оптимизацией.
Сложные структуры данных:
MongoDB может хранить произвольные глубоко вложенные структуры данных, но не может эффективно их искать. Если ваши данные образуют дерево, лес или график, вам необходимо хранить каждый узел и его ребра в отдельном документе. (Обратите внимание, что существуют хранилища данных, специально предназначенные для этого типа данных, которые также следует учитывать)
Также было указано, что невозможно вернуть подмножество элементов в документе. Если вам нужно выбрать несколько бит каждого документа, их будет легче выделить.
Согласованность данных
MongoDB делает компромисс между эффективностью и последовательностью. Правило состоит в том, что изменения в одном документе всегда являются атомарными, в то время как обновления нескольких документов никогда не следует считать атомарными. Также нет способа «заблокировать» запись на сервере (вы можете встроить это в логику клиента, используя, например, поле «блокировка»). При разработке схемы подумайте, как вы будете поддерживать согласованность данных. Как правило, чем больше вы храните в документе, тем лучше.
Для того, что вы описываете, я бы вставил комментарии и дал каждому комментарию поле id с ObjectID. ObjectID имеет встроенную метку времени, поэтому вы можете использовать ее вместо созданной в, если хотите.
источник
В общем, встраивание хорошо, если у вас есть отношения один-к-одному или один-ко-многим между сущностями, и ссылка хороша, если у вас есть отношения многие-ко-многим.
источник
Вы можете запросить по поддокументу:
db.question.find({'comments.content' : 'xxx'})
.Это вернет весь документ с вопросом. Чтобы отредактировать указанный комментарий, вам нужно найти комментарий на клиенте, выполнить редактирование и сохранить его обратно в БД.
В общем, если ваш документ содержит массив объектов, вы обнаружите, что эти подчиненные объекты необходимо будет изменить на стороне клиента.
источник
Ну, я немного опоздал, но все же хотел бы поделиться своим способом создания схемы.
У меня есть схемы для всего, что можно описать одним словом, как если бы вы делали это в классическом ООП.
НАПРИМЕР
Каждая схема может быть сохранена как документ или вложенный документ, поэтому я объявляю это для каждой схемы.
Документ:
поддокумент:
источник
Я наткнулся на эту небольшую презентацию, исследуя этот вопрос самостоятельно. Я был удивлен тем, насколько хорошо это было продумано, и информация и представление этого.
http://openmymind.net/Multiple-Collections-Versus-Embedded-Documents
Это подытожило:
источник
a lot
? 3? 10? 100? Чтоlarge
? 1kb? 1 МБ? 3 поля? 20 полей? Что такоеsmaller
/fewer
?Я знаю, что это довольно старо, но если вы ищете ответ на вопрос ОП о том, как вернуть только указанный комментарий, вы можете использовать оператор $ (query), например:
источник
Да, мы можем использовать ссылку в документе. Чтобы заполнить другой документ точно так же, как sql i joins. В mongo db у них нет соединений для сопоставления документа отношения один ко многим. Вместо этого мы можем использовать populate для выполнения нашего сценария.
Заполнение - это процесс автоматической замены указанных путей в документе документами из других коллекций. Мы можем заполнить один документ, несколько документов, простой объект, несколько простых объектов или все объекты, возвращаемые из запроса. Давайте посмотрим на некоторые примеры.
Лучше вы можете получить больше информации, пожалуйста, посетите: http://mongoosejs.com/docs/populate.html
источник
На самом деле, мне довольно любопытно, почему никто не говорил о спецификациях UML. Практическое правило заключается в том, что если у вас есть агрегация, то вы должны использовать ссылки. Но если это композиция, то связь сильнее, и вы должны использовать встроенные документы.
И вы быстро поймете, почему это логично. Если объект может существовать независимо от родителя, вы захотите получить к нему доступ, даже если родитель не существует. Поскольку вы просто не можете встроить его в несуществующий родительский объект, вы должны включить его в свою собственную структуру данных. И если родитель существует, просто свяжите их вместе, добавив ссылку на объект в родительском.
Не знаете, в чем разница между этими двумя отношениями? Вот ссылка, объясняющая их: Агрегация против Композиции в UML
источник
Я создал эту викторину как ссылку, чтобы узнать, следует ли вам использовать ту или иную
http://indie-rok.github.io/embedded-vs-reference-mongo-db
источник
Если вы отслеживали количество комментариев и индекс комментария, который хотите изменить, вы можете использовать оператор точки ( пример SO ).
Вы могли бы сделать, например,
(как еще один способ редактировать комментарии внутри вопроса)
источник