Исходная целостность в MongoDB. Что лучше?

Предположим, у меня есть Документ и авторские коллекции. Я мог бы спроектировать его двумя способами:

1-й способ:

documents
{_id:1, title:"document 1", author:"John", age: 34}
{_id:2, title: "document 2", author: "Maria", age:42 }
{_id:3, title: "document 3", author: "John", age: 34}

authors
{_id:1, name:"John", age:34}
{_id:2, name:"Maria", age:42}

Второй путь:

documents
{_id:1, title:"document 1", id_author:1}
{_id:2, title: "document 2", id_author: 2}
{_id:3, title: "document 3", id_author: 1}

authors
{_id:1, name:"John", age:34}
{_id:2, name:"Maria", age:42}

1-й способ хорош, потому что мне не нужно моделировать объединение, когда я получаю документ, у меня есть все данные в коллекции документов. Но, с другой стороны, если мне нужно изменить возраст Марии, я должен сделать это в обеих коллекциях.

Второй путь - наоборот, если мне нужен документ и возраст его автора, мне нужно сначала запросить документы, а затем авторов. Но хорошо, что, когда мне нужно изменить возраст Марии, мне нужно сделать это только в коллекции авторов.

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

Какой из наиболее часто используемых решений?

0
nl ja de

3 ответы

Обновление в более чем одной коллекции будет транзакцией. MongoDB не поддерживает транзакции.

Оба пути имеют свои недостатки.

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

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

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

2
добавлено
Обновление, которое происходит более чем в одной коллекции, не должно быть транзакционным, это просто функция парадигмы ACID. Вы также можете иметь транзакционное обновление для одной таблицы в программах, совместимых с ACID
добавлено автор Sammaye, источник
@Sammaye Конечно, транзакции могут произойти и на одной таблице. Я не могу вспомнить, что произошло обновление между двумя таблицами, которые не были транзакционными. Спасибо, спасибо.
добавлено автор Alderis Shyti, источник

Проблема с первым методом - это обновления:

{_id:1, title:"document 1", author:"John", age: 34}

Я могу представить, что на самом деле вам понадобится идентификатор автора, а также некоторые детали, которые вам нужны для запросов (резервирование схемы).

Это может создать проблему, как вы заметили:

Но, с другой стороны, если мне нужно изменить возраст Марии, я должен сделать это в обеих коллекциях.

Возраст меняется один раз в год, по крайней мере, и если у вас есть возраст неправильный, чаще. Имя также может измениться, особенно если позже вы обнаружите, что этот «Джон» имеет фамилию, или его имя на самом деле «Джонни».

Таким образом, проблема с созданием избыточности здесь заключается в том, что документ автора может сильно измениться, в результате чего вам придется запускать крайне неэффективные обновления, которые могут в любое время увеличить ваш рабочий набор. Что касается того, как часто это может вызвать это, я не могу сказать с предоставленной информацией, что вам решать.

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

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

Вы можете вставлять документы в автора. Это зависит от того, сколько документов вы хотите хранить, так как MongoDB имеет максимальный размер документа 16Meg.

Это говорит о возможности:

{
    _id: {},
    name: 'John',
    age: 43,
    documents: [
        { id: 1, title: "New Document" }
    ]
}

С одной стороны это использование операций с памятью, таких как $ pull или $ push , и не только это, но если ваш документ постоянно и значительно растет, вы можете см. фрагментацию.

Но опять же это всего лишь заметки для вас, но реальность зависит от информации, которая не предоставляется.

1
добавлено

Я бы предложил сочетание обоих подходов, «статическая» информация будет сохранена вместе с коллекцией документов, а переменные данные будут централизованы в коллекции авторов, только когда требуются данные переменной, я буду использовать идентификатор автора чтобы получить его возраст. Что-то вроде этого:

documents
{_id:"1", title:"document 1", author:"John", authorId: "1"}
{_id:"2", title: "document 2", author: "Maria", authorId: "2"}
{_id:"3", title: "document 3", author: "John", authorId: "1"}

authors
{_id:"1", name:"John", age:34}
{_id:"2", name:"Maria", age:42}

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

Как уже упоминалось, Mongo не является транзакционным, и у вас могут возникнуть проблемы, если вы создадите автора и документ за один выстрел.

1
добавлено
На самом деле большинство решений nosql (включая Djondb, db, которые я представляю) используют символы в качестве идентификаторов, поэтому я оставил бы его как символы, но да, тип на самом деле не имеет большого значения в решениях NoSQL (фиксированные ints теперь являются символами , просто ошибка копирования)
добавлено автор Cross, источник
Поле authorId не должно содержать строку «1», но номер 1.
добавлено автор Derick, источник
Хранение числа является более эффективным.
добавлено автор Derick, источник
DBA - русскоговорящее сообщество
DBA - русскоговорящее сообщество
1 345 участник(ов)

Общаемся и обсуждаем темы, посвященные DBA, PostgreSQL, Redis, MongoDB, MySQL, neo4j, riak и т.д. См. также: @devops_ru, @kubernetes_ru, @docker_ru, @nodejs_ru Рекомендуем сразу отключить уведомления, чтобы пребывание здесь было полезным и комфортным.

MongoDB Russian
MongoDB Russian
1 086 участник(ов)

> db.stats() https://combot.org/chat/-1001035023078