Вам бонус- начислено 1 монета за дневную активность. Сейчас у вас 1 монета

Моделирование данных, Отсутствие JOIN-ов, Массивы и вложенные документы в MongoDB и Денормализация кратко

Лекция



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

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

Отсутствие JOIN-ов в MongoDB

Первое и самое фундаментальное различие, с которым вам надо свыкнуться, это отсутствие у MongoDB аналога конструкции JOIN.

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

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

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

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

Вместо этого нам нужно вручную выполнять операции JOIN в коде нашего приложения. По сути, мы должны выполнить второй запрос, чтобы найти связанные данные. Это действие аналогично созданию внешних ключей в реляционных базах данных. Теперь давайте перейдем от примера с единорогами к примеру с сотрудниками. Сначала мы создадим запись о сотруднике (я явно указываю здесь _id, чтобы наши примеры были последовательными).

db.employees.insert({_id: ObjectId("wefewfwefewf"), name: 'Intellect'}) 

Теперь добавим пару сотрудников и сделаем Intellect их менеджером:

db.employees.insert({_id: ObjectId("4d85c7039awefwef117d731"), name: 'Duncan', manager: ObjectId("4d85c70wefwef70a117d730")}); 
db.employees.insert({_id: ObjectId("4d85c7039abwefewf17d732"), name: 'Moneo', manager: ObjectId("4d85c7wefwefew70a117d730")});

(стоит повторить, что _id может быть любым уникальным значением. Поскольку в жизни вы скорее всего станете использовать ObjectId, мы также здесь используем его.)

Чтобы найти всех сотрудников, принадлежащих Intellect, выполним просто:

db.employees.find({manager: ObjectId("4d85c7039aewfewfewfd730")}) 

Никакой магии. В худших случаях отсутствие JOIN-ов чаще всего потребует дополнительного запроса (как правило индексированного).

Массивы и вложенные документы в mongodb

Однако то что у MongoDB нет JOIN-ов копенсируется другими плюшками.

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

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

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

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

Вы помните, что мы ранее кратко упомянули о том, как MongoDB поддерживает массивы как объекты первого класса? Это оказывается очень удобным, особенно когда нужно моделировать отношения типа "один-ко-многим" или "многие-ко-многим". Например, допустим, у сотрудника может быть несколько менеджеров, в этом случае мы просто можем сохранить их в виде массива:

db.employees.insert({_id: ObjectId("4d85c7039wefwef17d733"), name: 'Siona', manager: [ObjectId("4d85c7wefwefa117d730"), ObjectId("4d85c7039ab0fdwefewf732")] }) 

А самое интересное, что в одних документах manager можно сделать скалярным значением, а в других - массивом. А наш предыдущий запрос find сработает в обоих случаях:

db.employees.find({manager: ObjectId("4d85edewdewd70a117d730")})

Вскоре вы убедитесь, что массивы значений намного удобнее в использовании, нежели таблицы связи "многие-ко-многим". Кроме массивов MongoDB также поддерживает вложенные документы. Попробуйте вставить документ со вложенным документом, например:

db.employees.insert({_id: ObjectId("4dHULEIHWEpeowkf734"), name: 'Ghanima', family: {mother: 'Chani', father: 'Paul', brother: ObjectId("dsfSDvSSverervrev")}}) 

Вложенные документы можно запрашивать с помощью точечной нотации:

db.employees.find({'family.mother': 'Chani'}) 

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

DBRef в MongoDB механизм для работы с ссылками между документами

MongoDB поддерживает понятие под названием DBRef, которое является соглашением, принятым во многих драйверах.

В MongoDB существует специальный механизм для работы с ссылками между документами, который называется DBRef (Database Reference). DBRef представляет собой способ создания ссылок на документы в других коллекциях базы данных.

С помощью DBRef вы можете создавать ссылки на другие документы, указывая их идентификаторы (_id) и название соответствующей коллекции. Это позволяет установить связи между документами, даже если они находятся в разных коллекциях.

Однако следует отметить, что DBRef не является встроенной функцией MongoDB, а скорее это стандартный способ представления ссылок, рекомендованный в официальной документации. Использование DBRef предоставляет гибкость при управлении связями между документами, но также требует некоторой дополнительной работы по обработке ссылок в коде приложения.

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

Когда драйвер видит DBRef, он может автоматически получить связанный документ. DBRef включает в себя коллекцию и _id документа, на который он ссылается. Это означает следующее - документы из одной и той же коллекции могут ссылаться на другие документы из различных коллекций. То есть документ 1 может ссылаться на документ из коллекции managers, в то же время документ 2 может ссылаться на документ из коллекции employees.

Денормализация

Еще одним вариантом, помимо использования JOIN-операций, является денормализация данных. Исторически денормализация применялась для улучшения производительности или в случаях, когда требовалась возможность сохранить снимок данных (как, например, в журнале аудита). Однако с появлением множества NoSQL-решений, которые не поддерживают JOIN-ы, денормализация стала распространенной практикой. Это не означает, что нужно просто дублировать все данные в каждом документе. Вместо этого можно избегать избыточности данных, размышляя о структуре базы данных.

Давайте представим, что мы разрабатываем форум. Традиционный подход к связыванию пользователя с его постом включает столбец userid в таблице "посты". Однако с такой моделью нельзя легко получить список постов без дополнительных операций (JOIN) с таблицей пользователей. Возможным решением является хранение имени пользователя (name) вместе с userid для каждого поста. Также можно включить небольшой встроенный документ, содержащий информацию о пользователе, чтобы избежать дополнительных JOIN-ов при запросах.

user: {id: ObjectId('Something'), name: 'Intellect'}.

Да, если позволить пользователям изменять свое имя, нам придется обновлять каждый документ (пост) - это один лишний запрос.

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

Что лучше использовать?

Также полезным подходом в ситуациях, где присутствует отношение "один-ко-многим" или "многие-ко-многим", является использование массива идентификаторов. Существует мнение о том, что DBRef не так часто применяется, но, конечно же, вы можете самостоятельно попробовать его в своей работе. Обычно начинающие разработчики испытывают неуверенность в выборе между использованием вложенных документов и DBRef, чтобы определить, что подойдет их ситуации лучше.

Во-первых, следует помнить, что одиночный документ ограничен в размере до 4 мегабайт. Факт ограничения (пусть и такого щедрого) размера документа дает понимание о том, как их следует использовать. Теперь понятно, что большинство разработчиков склоняются к использованию заданных вручную ссылок. Вложенные документы используются часто, но для небольших объемов данных, если их желательно всегда извлекать вместе с родительским документом. Примером из жизни может быть документ accounts, сохраняемый с каждым пользователем, например:

db.users.insert({name: 'Intellect', email: 'intellect@intellect.icu', account: {allowed_gholas: 5, spice_ration: 10}}) 

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

Мало или много коллекций MongoDB

Учитывая, что в MongoDB нет жестких схем для коллекций, есть возможность использовать одну коллекцию, содержащую документы разной структуры. Примеры систем, построенных на MongoDB, с которыми мне доводилось работать, часто напоминают реляционные базы данных. Другими словами, то, что было бы таблицей в реляционной базе данных, обычно реализуется как коллекция в MongoDB (хотя таблицы для связей "многие-ко-многим" являются исключением).

Однако дело меняется, если применяются вложенные документы. Хороший пример - это блог. Предположим, у нас есть коллекция "посты" и "комментарии", и каждый пост должен содержать в себе массив вложенных комментариев. За исключением ограничения размера в 4 МБ (и то, "Гамлет" на английском не так велик), многие разработчики предпочитают разделять сущности. Это делает структуру более понятной и четкой.

В моделировании данных в MongoDB нет жестких правил (за исключением ограничения в 4 МБ). Вам стоит экспериментировать с разными подходами, чтобы определить, что будет работать наилучшим образом.

Цель этой части заключалась в том, чтобы предоставить некоторые полезные рекомендации для проектирования данных в MongoDB. Вы можете рассматривать их как отправную точку. Моделирование в документ-ориентированных системах отличается от реляционных, но не настолько сильно. Здесь есть больше гибкости, хотя существует ограничение размера 4 МБ, которое обычно хорошо подходит для большинства новых систем. Принципиально важно только то, чтобы пробовать и экспериментировать.

Вау!! 😲 Ты еще не читал? Это зря!

создано: 2020-12-18
обновлено: 2023-08-17
132265



Рейтиг 9 of 10. count vote: 2
Вы довольны ?:


Поделиться:

Найди готовое или заработай

С нашими удобными сервисами без комиссии*

Как это работает? | Узнать цену?

Найти исполнителя
$0 / весь год.
  • У вас есть задание, но нет времени его делать
  • Вы хотите найти профессионала для выплнения задания
  • Возможно примерение функции гаранта на сделку
  • Приорететная поддержка
  • идеально подходит для студентов, у которых нет времени для решения заданий
Готовое решение
$0 / весь год.
  • Вы можите продать(исполнителем) или купить(заказчиком) готовое решение
  • Вам предоставят готовое решение
  • Будет предоставлено в минимальные сроки т.к. задание уже готовое
  • Вы получите базовую гарантию 8 дней
  • Вы можете заработать на материалах
  • подходит как для студентов так и для преподавателей
Я исполнитель
$0 / весь год.
  • Вы профессионал своего дела
  • У вас есть опыт и желание зарабатывать
  • Вы хотите помочь в решении задач или написании работ
  • Возможно примерение функции гаранта на сделку
  • подходит для опытных студентов так и для преподавателей



Комментарии


Оставить комментарий
Если у вас есть какое-либо предложение, идея, благодарность или комментарий, не стесняйтесь писать. Мы очень ценим отзывы и рады услышать ваше мнение.
To reply

MongoDB

Термины: MongoDB