Чтобы овладеть принципами организации данных в реляционных базах, нужно не только знать формы нормализации и реляционную алгебру. Важно понимать смыслы, которые лежат вне области программирования.
Программы, которые пишут программисты, всегда создаются под определенную предметную область. Например, бухгалтерский софт основывается на правилах ведения бухгалтерского учета, а сайт для просмотра сериалов — на таких понятиях из телеиндустрии, как «сезон» или «эпизод».
Понимать предметную область, для которой вы пишете программу, так же важно, как и уметь программировать. Иногда область может быть по-настоящему сложной, например, бухгалтерия или технологическое производство. Но общее понимание все же требуется.
В этом уроке мы узнаем, что такое онтология и как она помогает описывать предметную область программы и показывать связи ее сущностей. В итоге мы разберем каждый тип связи и поймем, в каких случаях они будут полезны. Также рассмотрим, как эти связи визуализируются.
Что такое онтология
Рассмотрим Хекслет, так как вы с ним знакомы. Чтобы понимать предметную область Хекслета, нужно выделить ключевые понятия — сущности, вокруг которых строится вся логика. У обучающих ресурсов это, как правило, «курс» и «урок». Но на самом деле сущностей гораздо больше.
В случае Хекслета еще можно выделить «профессию», «испытание», «code review», «квиз», «участника курса», «проект». Этот список можно продолжать еще долго. Но сущности не существуют сами по себе, а находятся во взаимоотношениях друг с другом.
Например, квиз содержит или агрегирует в себе вопросы, в которых есть ответы. Профессия состоит из курсов, а курсы из уроков, уроки — из теории, квиза и практики. Эти связи имеют конкретные названия:
Один ко многим, one-to-many или o2m. Например, когда один урок может находиться только в одном курсе, но курс содержит множество уроков
Один к одному, one-to-one или o2o. Например, на Хекслете такая связь установлена между пользователем и аккаунтом на Facebook
Многие ко многим, many-to-many или m2m. Например, когда один курс могут проходить много пользователей, и один пользователь может проходить много курсов
Так это выглядит на схеме:
Описание объектов рассматриваемой области и связей между ними называется онтологией предметной области. Эту онтологию хорошо знают эксперты соответствующей области: в бухгалтерии — бухгалтер, в обучении — преподаватель. Но, в отличие от программистов, они часто представляют ее на интуитивном уровне, неформально.
На практике программисты, бизнес-аналитики или менеджеры общаются с заказчиками, которые могут сами выступать в роли экспертов, и строят вместе с ними формальную онтологию. То есть выделяют конкретные термины, договариваются, что они означают и как связаны друг с другом.
Затем с помощью ER-модели программист формирует необходимую модель данных. Необязательно на бумаге или в специализированных программах. Чаще такая модель существует только в голове и коде.
Эта модель и становится основной для проектирования базы данных. Каждая сущность в реляционной базе данных представлена таблицей, а связи между сущностями реализуются через внешние ключи.
Чтобы визуализировать ER-модель, используют диаграмму Entity-Relationship Diagram (ERD). Познакомимся с ней.
Что такое ERD
У ER-модели нет графического представления, поэтому используют ERD. Многие понимают под ER-моделью и ERD одно и то же. Хотя ER-модель можно представить и с помощью других нотаций.
В ERD каждая сущность представлена блоком, в котором перечисляются поля. Между блоками рисуются линии, у которых есть некоторые заранее определенные концы. Они определяют тип связи между сущностями:
Рассмотрим подробнее каждый вид связи.
Один ко многим (one-to-many)
Один ко многим — наиболее распространенный вид связи. Например, один лектор может вести несколько курсов:
Технически, такая связь организуется через внешний ключ, который добавляется в зависимую сущность — many.
Допустим, у нас есть две исходные таблицы:
users
id | first_name | last_name | created_at |
---|---|---|---|
1 | Сергей | Петров | 11.10.2005 |
38 | Иван | Носов | 03.08.2000 |
22 | Виктор | Пирогов | 23.12.2011 |
emails
id | user_id | |
---|---|---|
1 | 1 | serj@gmail.com |
2 | 1 | petrov@mail.ru |
10 | 38 | ivan@yahoo.com |
22 | 22 | vkurg@indbox.com |
Чтобы узнать все адреса почты, которые есть у пользователя с идентификатором 1
, нужно выполнить такой запрос:
SELECT * FROM emails WHERE user_id = 1;
Один к одному (one-to-one)
На схеме такая связь выглядит так:
Например, у каждой страны есть одна столица:
countries
id | name | created_at |
---|---|---|
2 | Russia | 11.10.2005 |
38 | Spain | 03.08.2000 |
22 | Germany | 23.12.2011 |
cities
id | name | country_id | capital | created_at |
---|---|---|---|---|
34 | Moscow | 2 | true | 11.10.2005 |
33 | Valencia | 38 | 03.08.2000 | |
99 | Voronezh | 2 | 23.12.2011 | |
4 | Ulyanovsk | 2 | 23.12.2011 | |
5 | Berlin | 22 | true | 23.12.2011 |
Связь one-to-one обычно существует не сама по себе, а внутри связи one-to-many. То есть у каждой страны есть города, но только один из них столица.
SELECT * FROM cities WHERE country_id = 38 AND capital = true;
Многие ко многим (many-to-many)
Такие связи можно отобразить так:
Многие ко многим встречается очень часто. Например, у каждого человека множество друзей, каждый человек друг для множества других. Или один человек проходит множество курсов, один курс проходится множеством людей.
Эта связь реализуется уже не так просто. Технически невозможно связать две таблицы связью many-to-many без введения третьей таблицы.
Например, у нас есть две исходные таблицы:
users
id | first_name | created_at |
---|---|---|
2 | Сергей | 11.10.2005 |
38 | Иван | 03.08.2000 |
22 | Виктор | 23.12.2011 |
courses
id | name | created_at |
---|---|---|
8 | PHP basics | 11.10.2005 |
55 | Python basics | 03.08.2000 |
22 | Ruby basics | 23.12.2011 |
Эта таблица будет связующей:
course_members
id | user_id | course_id | created_at |
---|---|---|---|
34 | 2 | 8 | 11.10.2005 |
33 | 38 | 55 | 03.08.2000 |
99 | 22 | 22 | 23.12.2011 |
4 | 22 | 8 | 23.12.2011 |
5 | 38 | 22 | 23.12.2011 |
В таблице course_members
есть свой первичный ключ, и каждая запись содержит ссылки как на конкретный курс, так и на конкретного пользователя. На Хекслете эта таблица начинает заполняться в тот момент, когда пользователь нажимает кнопку «Вступить в курс». Для юзера создается запись с его идентификатором и идентификатором курса, который он собрался проходить.
Если мы захотим узнать все курсы, которые проходит пользователь, то выполним такой запрос:
SELECT course_id FROM course_members WHERE user_id = 3;
Если захотим узнать, кто проходит данный курс, то такой запрос:
SELECT user_id FROM course_members WHERE course_id = 3;
Такая структура соблюдается для любых двух сущностей, которые надо связать. В общем виде схема выглядит так:
Есть исходные таблицы A и B. Для них создается новая таблица AB. Внутри нее есть два внешних ключа — a_id и b_id, которые связаны с исходными таблицами.
Как показывает практика, такая промежуточная таблица часто становится самостоятельной сущностью. Если брать курсы, то важно понимать, закончил ли пользователь курс или нет, когда конкретно он это сделал, сколько заданий решил. Вся эта информация может храниться только в одном месте — в связанной таблице.
Выводы
В этом уроке мы узнали, что онтология помогает описывать предметную область программы и показывать связи ее сущностей. В реляционных базах данных используют три типа связи: один ко многим, один к одному и многие ко многим. А визуализируются они с помощью Entity-Relationship Diagram.
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
- Статья «Как учиться и справляться с негативными мыслями»
- Статья «Ловушки обучения»
- Статья «Сложные простые задачи по программированию»
- Вебинар «Как самостоятельно учиться»