ER-диаграмма
Диаграмма сущность-связь (сокращённо ER-диаграмма) описывает взаимосвязанные объекты интереса в определённой предметной области. Базовая ER-диаграмма состоит из типов сущностей (используемых для классификации объектов интереса) и указывает отношения, которые могут существовать между сущностями (экземплярами этих типов сущностей),Обратите внимание, что на практике при работе с ER-диаграммами «тип сущности» почти всегда сокращают до «сущность». Например, «тип сущности CUSTOMER» обычно называют просто «сущность CUSTOMER». Такая практика очень распространена, поэтому не рекомендуется использовать другие способы; однако технически сущность — это абстрактный экземпляр типа сущности, и ER-диаграмма показывает именно эти абстрактные экземпляры и отношения между ними. Именно поэтому сущности всегда именуются существительными в единственном числе.
Копировать
Встраивание
---
title: Order example
---
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
Имена сущностей обычно пишутся в верхнем регистре, хотя общепринятого стандарта на этот счёт нет, и синтаксис Mermaid этого не требует.
Отношения между сущностями обозначаются линиями с маркерами на концах, обозначающими кардинальность. Mermaid использует наиболее популярное обозначение «вороньей лапки», которое наглядно показывает, что у сущности, с которой оно соединено, может быть несколько экземпляров.
ER-диаграммы могут использоваться для различных целей: от абстрактных логических моделей, не содержащих деталей реализации, до физических моделей таблиц реляционных баз данных. Включение определений атрибутов на ER-диаграмме помогает понять назначение и смысл сущностей; эти определения атрибутов не обязательно должны быть исчерпывающими, обычно достаточно небольшой части атрибутов. Mermaid позволяет определять их по типу и имени.
Копировать
Встраивание
erDiagram
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
string name
string custNumber
string sector
}
ORDER ||--|{ LINE-ITEM : contains
ORDER {
int orderNumber
string deliveryAddress
}
LINE-ITEM {
string productCode
int quantity
float pricePerUnit
}
При включении атрибутов на ER-диаграмму вы должны решить, включать ли внешние ключи в качестве атрибутов; это может зависеть от того, насколько вы хотите отразить структуру таблиц отношений. Если ваша диаграмма является логической моделью и не предполагает реализации отношений, то лучше не включать эти атрибуты, поскольку связи-ассоциации уже передают способ связи между сущностями. Например, структура данных JSON может реализовывать отношение «один ко многим» с помощью массива без атрибутов внешнего ключа. Аналогично, объектно-ориентированные языки программирования могут использовать указатели или ссылки на коллекции. Даже для моделей, предназначенных для реляционной реализации, можно считать, что включение атрибутов внешнего ключа дублирует информацию, передаваемую связью, и не добавляет смысла сущности.
Синтаксис
Сущности и отношения
Синтаксис Mermaid для ER-диаграмм совместим с PlantUML и расширяет функциональность для обозначения отношений. Каждый оператор включает следующее:
Копировать
Встраивание
<first-entity> [<relationship> <second-entity> : <relationship-label>]
- first-entity — это имя первой сущности. Имя поддерживает любые символы Unicode и, если заключено в двойные кавычки, может содержать пробелы.
- relationship описывает взаимное отношение между двумя сущностями.
- second-entity — это имя другой сущности.
- relationship-label описывает отношение с точки зрения первой сущности.
Например:
Копировать
Встраивание
PROPERTY ||--|{ ROOM : contains
Это утверждение можно понять так: один объект недвижимости содержит одну или несколько комнат, а комната принадлежит только одному объекту недвижимости. Здесь метка рассматривается с точки зрения первой сущности: объект недвижимости содержит комнату, но комната не содержит объект недвижимости. С точки зрения второй сущности эквивалентную метку обычно легко вывести.
Обязательной является только часть first-entity. Это позволяет отображать сущности без отношений, что очень полезно при итеративном построении диаграммы. Если указаны другие части оператора, то все части обязательны.
Текст Unicode
Имена сущностей, отношения и атрибуты поддерживают текст unicode.
Копировать
Встраивание
erDiagram
"This ❤ Unicode"
Синтаксис отношений
Часть отношения в каждом операторе можно разбить на три подчасти:
- Кардинальность первой сущности относительно второй
- Придаёт ли это отношение дочерней сущности идентифицирующий характер
- Кардинальность второй сущности относительно первой
Кардинальность — это атрибут, описывающий количество элементов другой сущности, которые могут быть связаны с рассматриваемой сущностью. В приведённом выше примере один PROPERTY может быть связан с одним или несколькими экземплярами ROOM, а один ROOM может быть связан только с одним PROPERTY. В каждом маркере кардинальности два символа: самый внешний символ обозначает максимальное значение, самый внутренний — минимальное. В таблице ниже обобщены возможные значения кардинальности:
| Значение (слева) | Значение (справа) | Значение |
|---|---|---|
| |o | o| | Ноль или один |
| || | || | Ровно один |
| }o | o{ | Ноль или несколько (без верхнего предела) |
| }| | |{ | Один или несколько (без верхнего предела) |
| Значение (слева) | Значение (справа) | Значение |
|---|---|---|
| one or zero | one or zero | Ноль или один |
| zero or one | zero or one | Ноль или один |
| one or more | one or more | Один или несколько |
| one or many | one or many | Один или несколько |
| many(1) | many(1) | Один или несколько |
| 1+ | 1+ | Один или несколько |
| zero or more | zero or more | Ноль или несколько |
| zero or many | zero or many | Ноль или несколько |
| many(0) | many(0) | Ноль или несколько |
| 0+ | 0+ | Ноль или несколько |
| only one | only one | Ровно один |
| 1 | 1 | Ровно один |
Идентификация
Отношения можно разделить на идентифицирующие и неидентифицирующие, которые отображаются соответственно сплошной или пунктирной линией. Это важно, когда одна из сущностей не может существовать самостоятельно без другой. Например, компании, предоставляющей страхование вождения автомобилей для людей, может потребоваться хранить данные NAMED-DRIVER. При моделировании мы можем сначала заметить, что одним CAR могут управлять многие PERSON, а один PERSON может управлять многими CAR , и оба могут существовать без другого, поэтому это неидентифицирующее отношение, которое в Mermaid можно задать так: PERSON }|..|{ CAR : "driver". Обратите внимание на две точки в середине отношения, которые приведут к отрисовке пунктирной линии между двумя сущностями. Однако когда это отношение «многие ко многим» разделяется на два отношения «один ко многим», мы замечаем, что без PERSON и CAR существование NAMED-DRIVER невозможно. Эти отношения становятся идентифицирующими и обозначаются дефисом, что соответствует сплошной линии:
| Значение | Псевдоним |
|---|---|
| -- | Идентифицирующее |
| .. | Неидентифицирующее |
| Значение | 别名为 |
|---|---|
| to | Идентифицирующее |
| optionally to | Неидентифицирующее |
Копировать
Встраивание
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
PERSON }o..o{ NAMED-DRIVER : is
Копировать
Встраивание
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
PERSON }o--o{ NAMED-DRIVER : is
Атрибут
Для сущности можно определить атрибуты, указав имя сущности, за которым следует блок с несколькими парами type name, при этом блок заключается в фигурные скобки {}. Атрибуты отображаются внутри блока сущности, например:
Копировать
Встраивание
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
CAR {
string registrationNumber
string make
string model
}
PERSON ||--o{ NAMED-DRIVER : is
PERSON {
string firstName
string lastName
int age
}
Значение type должно начинаться с буквенного символа и может содержать цифры, дефисы, знаки подчёркивания, круглые скобки и квадратные скобки. Значение name следует формату, аналогичному type, но также может начинаться со звёздочки, что является ещё одним способом указать, что атрибут является первичным ключом. Помимо этого, других ограничений нет, и нет неявного набора допустимых типов данных.
Псевдоним сущности
Для добавления псевдонима сущности можно использовать квадратные скобки. Если псевдоним указан, на диаграмме будет отображаться псевдоним вместо имени сущности; псевдоним подчиняется всем тем же правилам, что и имя сущности.
Копировать
Встраивание
erDiagram
p[Person] {
string firstName
string lastName
}
a["Customer Account"] {
string email
}
p ||--o| a : has
Ключи и комментарии атрибутов
Атрибуты также могут определять ключи или комментарии. Ключ может быть первичным ключом (PK), внешним ключом (FK) или уникальным ключом (UK). Чтобы указать несколько ограничений ключа для одного атрибута, разделите их запятыми (например, PK, FK). Комментарий определяется с помощью двойных кавычек в конце атрибута; комментарий не может содержать символ двойной кавычки.
Копировать
Встраивание
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
CAR {
string registrationNumber PK
string make
string model
string[] parts
}
PERSON ||--o{ NAMED-DRIVER : is
PERSON {
string driversLicense PK "The license #"
string(99) firstName "Only 99 characters are allowed"
string lastName
string phone UK
int age
}
NAMED-DRIVER {
string carRegistrationNumber PK, FK
string driverLicence PK, FK
}
MANUFACTURER ||--o{ CAR : makes
Направление
Оператор направления объявляет направление диаграммы.
TB объявляет направление диаграммы сверху вниз, BT может изменить его на противоположное — снизу вверх.
Копировать
Встраивание
erDiagram
direction TB
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
string name
string custNumber
string sector
}
ORDER ||--|{ LINE-ITEM : contains
ORDER {
int orderNumber
string deliveryAddress
}
LINE-ITEM {
string productCode
int quantity
float pricePerUnit
}
LR объявляет направление диаграммы слева направо, RL может изменить его на противоположное — справа налево.
Копировать
Встраивание
erDiagram
direction LR
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
string name
string custNumber
string sector
}
ORDER ||--|{ LINE-ITEM : contains
ORDER {
int orderNumber
string deliveryAddress
}
LINE-ITEM {
string productCode
int quantity
float pricePerUnit
}
Настройка стиля узла
К узлу можно применить определённый стиль, например более толстую рамку или другой цвет фона.
Копировать
Встраивание
erDiagram
id1||--||id2 : label
style id1 fill:pink,stroke:yellow,stroke-width:4px
style id2 fill:#69d,stroke:#f96,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
Также можно прикрепить стиль к списку узлов в одном операторе:
Копировать
Встраивание
style nodeId1,nodeId2 styleList
Класс
Вместо определения стиля каждый раз удобнее определить класс стиля и прикрепить этот класс к узлам, которым нужен другой внешний вид.
Определение класса показано в следующем примере:
Копировать
Встраивание
classDef className fill:pink,stroke:#333,stroke-width:4px
Также можно определить несколько классов в одном операторе:
Копировать
Встраивание
classDef firstClassName,secondClassName font-size:12pt
Синтаксис прикрепления класса к узлу таков:
Копировать
Встраивание
class nodeId1 className
Также можно прикрепить класс к списку узлов в одном операторе:
Копировать
Встраивание
class nodeId1,nodeId2 className
Также можно прикрепить несколько классов одновременно:
Копировать
Встраивание
class nodeId1,nodeId2 className1,className2
Простой способ добавления класса — использовать оператор :::, чтобы прикрепить имя класса к узлу, как показано ниже:
Копировать
Встраивание
erDiagram
direction TB
CAR:::someclass {
string registrationNumber
string make
string model
}
PERSON:::someclass {
string firstName
string lastName
int age
}
HOUSE:::someclass
classDef someclass fill:#f96
Объявить отношения между сущностями можно с помощью следующего синтаксиса:
Копировать
Встраивание
erDiagram
CAR {
string registrationNumber
string make
string model
}
PERSON {
string firstName
string lastName
int age
}
PERSON:::foo ||--|| CAR : owns
PERSON o{--|| HOUSE:::bar : has
classDef foo stroke:#f00
classDef bar stroke:#0f0
classDef foobar stroke:#00f
Подобно оператору class, сокращённый синтаксис также может применить несколько классов одновременно:
Копировать
Встраивание
nodeId:::className1,className2
Класс по умолчанию
Если класс назван default, он будет назначен всем узлам, не имеющим определённого класса.
Копировать
Встраивание
classDef default fill:pink,stroke:#333,stroke-width:4px;
Примечание: пользовательские стили из операторов стиля или других классов имеют приоритет и переопределяют стиль по умолчанию. (Например, класс default задаёт узлу розовый фон, но если применить класс blue, узел получит синий цвет фона.)
Копировать
Встраивание
erDiagram
CAR {
string registrationNumber
string make
string model
}
PERSON {
string firstName
string lastName
int age
}
PERSON:::foo ||--|| CAR : owns
PERSON o{--|| HOUSE:::bar : has
classDef default fill:pink,stroke-width:4px
classDef foo stroke:#f90
classDef bar stroke:#ff0
classDef foobar stroke:#69f
Конфигурация
Макет
Макет диаграммы обрабатывается функцией render(); макетом по умолчанию является макет ELK, подходящий для больших и более сложных диаграмм.
Чтобы вместо этого использовать классический макет Dagre, вы можете задать его в config YAML frontmatter
Копировать
Встраивание
---
config:
layout: dagre
---
Содержимое кода Mermaid следующее:
Копировать
Встраивание
---
title: Order example
config:
layout: elk
---
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses