mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-12-21 11:47:27 +01:00
fix: use compositional syntax for aggregation relationships
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
This commit is contained in:
@@ -463,9 +463,9 @@ ORDER ||--|{ LINE-ITEM : contains
|
|||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
erDiagram
|
erDiagram
|
||||||
DEPARTMENT <> EMPLOYEE : contains
|
DEPARTMENT ||<>--|| EMPLOYEE : contains
|
||||||
PROJECT <>.. TASK : manages
|
PROJECT o{<>..o{ TASK : manages
|
||||||
TEAM <> MEMBER : consists_of
|
TEAM ||<>--|| MEMBER : consists_of
|
||||||
`,
|
`,
|
||||||
{ logLevel: 1 }
|
{ logLevel: 1 }
|
||||||
);
|
);
|
||||||
@@ -475,7 +475,7 @@ ORDER ||--|{ LINE-ITEM : contains
|
|||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
erDiagram
|
erDiagram
|
||||||
DEPARTMENT <> EMPLOYEE : contains
|
DEPARTMENT ||<>--o{ EMPLOYEE : contains
|
||||||
DEPARTMENT {
|
DEPARTMENT {
|
||||||
int id PK
|
int id PK
|
||||||
string name
|
string name
|
||||||
@@ -495,9 +495,9 @@ ORDER ||--|{ LINE-ITEM : contains
|
|||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
erDiagram
|
erDiagram
|
||||||
UNIVERSITY <> COLLEGE : "has multiple"
|
UNIVERSITY ||<>--o{ COLLEGE : "has multiple"
|
||||||
COLLEGE <> DEPARTMENT : "contains"
|
COLLEGE ||<>--o{ DEPARTMENT : "contains"
|
||||||
DEPARTMENT <> FACULTY : "employs"
|
DEPARTMENT ||<>--o{ FACULTY : "employs"
|
||||||
`,
|
`,
|
||||||
{ logLevel: 1 }
|
{ logLevel: 1 }
|
||||||
);
|
);
|
||||||
@@ -509,8 +509,8 @@ ORDER ||--|{ LINE-ITEM : contains
|
|||||||
erDiagram
|
erDiagram
|
||||||
CUSTOMER ||--o{ ORDER : places
|
CUSTOMER ||--o{ ORDER : places
|
||||||
ORDER ||--|{ ORDER_ITEM : contains
|
ORDER ||--|{ ORDER_ITEM : contains
|
||||||
PRODUCT <> ORDER_ITEM : "aggregated in"
|
PRODUCT ||<>--o{ ORDER_ITEM : "aggregated in"
|
||||||
WAREHOUSE <>.. PRODUCT : "stores"
|
WAREHOUSE o{<>..o{ PRODUCT : "stores"
|
||||||
`,
|
`,
|
||||||
{ logLevel: 1 }
|
{ logLevel: 1 }
|
||||||
);
|
);
|
||||||
@@ -525,8 +525,8 @@ ORDER ||--|{ LINE-ITEM : contains
|
|||||||
p[PROJECT]
|
p[PROJECT]
|
||||||
t[TASK]
|
t[TASK]
|
||||||
|
|
||||||
d <> e : contains
|
d ||<>--|| e : contains
|
||||||
p <>.. t : manages
|
p o{<>..o{ t : manages
|
||||||
|
|
||||||
`,
|
`,
|
||||||
{ logLevel: 1 }
|
{ logLevel: 1 }
|
||||||
@@ -537,11 +537,34 @@ ORDER ||--|{ LINE-ITEM : contains
|
|||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
erDiagram
|
erDiagram
|
||||||
COMPANY <> DEPARTMENT : owns
|
COMPANY ||<>--o{ DEPARTMENT : owns
|
||||||
DEPARTMENT <> EMPLOYEE : contains
|
DEPARTMENT ||<>--o{ EMPLOYEE : contains
|
||||||
EMPLOYEE <> PROJECT : works_on
|
EMPLOYEE o{<>--o{ PROJECT : works_on
|
||||||
PROJECT <> TASK : consists_of
|
PROJECT ||<>--o{ TASK : consists_of
|
||||||
TASK <> SUBTASK : includes
|
TASK ||<>--o{ SUBTASK : includes
|
||||||
|
`,
|
||||||
|
{ logLevel: 1 }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render aggregation with different cardinalities', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
|
erDiagram
|
||||||
|
COMPANY ||<>--o{ DEPARTMENT : has
|
||||||
|
MANAGER o|<>..o| TEAM : leads
|
||||||
|
PRODUCT |{<>--|{ CATEGORY : belongs_to
|
||||||
|
`,
|
||||||
|
{ logLevel: 1 }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render aggregation with zero-or-one relationships', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
|
erDiagram
|
||||||
|
PERSON o|<>--o| PASSPORT : owns
|
||||||
|
EMPLOYEE o|<>..o| PARKING_SPOT : assigned
|
||||||
`,
|
`,
|
||||||
{ logLevel: 1 }
|
{ logLevel: 1 }
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -213,37 +213,67 @@ erDiagram
|
|||||||
|
|
||||||
Aggregation represents a "has-a" relationship where the part can exist independently of the whole. This is different from composition, where the part cannot exist without the whole. Aggregation relationships are rendered with hollow diamond markers at the endpoints.
|
Aggregation represents a "has-a" relationship where the part can exist independently of the whole. This is different from composition, where the part cannot exist without the whole. Aggregation relationships are rendered with hollow diamond markers at the endpoints.
|
||||||
|
|
||||||
| Value | Alias for | Description |
|
Aggregation syntax follows a compositional pattern where you combine cardinality markers with the aggregation symbol (`<>`) and line type:
|
||||||
| :---: | :------------------: | ------------------------------ |
|
|
||||||
| <> | _aggregation_ | Basic aggregation (solid line) |
|
**Syntax:**
|
||||||
| <>.. | _aggregation-dashed_ | Dashed aggregation line |
|
|
||||||
|
```
|
||||||
|
<first-entity> <cardinalityA><>--<cardinalityB> <second-entity> : <relationship-label>
|
||||||
|
<first-entity> <cardinalityA><>..<cardinalityB> <second-entity> : <relationship-label>
|
||||||
|
```
|
||||||
|
|
||||||
|
Where:
|
||||||
|
|
||||||
|
- `<>` is the aggregation marker
|
||||||
|
- `--` represents a solid line (identifying relationship)
|
||||||
|
- `..` represents a dashed line (non-identifying relationship)
|
||||||
|
- Cardinality markers can be: `||` (only one), `o|` (zero or one), `o{` (zero or more), `|{` (one or more)
|
||||||
|
|
||||||
**Examples:**
|
**Examples:**
|
||||||
|
|
||||||
```mermaid-example
|
```mermaid-example
|
||||||
erDiagram
|
erDiagram
|
||||||
DEPARTMENT <> EMPLOYEE : contains
|
DEPARTMENT ||<>--o{ EMPLOYEE : contains
|
||||||
PROJECT <>.. TASK : manages
|
PROJECT o{<>..o{ TASK : manages
|
||||||
TEAM <> MEMBER : consists_of
|
TEAM ||<>--|| MEMBER : consists_of
|
||||||
|
COMPANY ||<>--o{ DEPARTMENT : owns
|
||||||
```
|
```
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
erDiagram
|
erDiagram
|
||||||
DEPARTMENT <> EMPLOYEE : contains
|
DEPARTMENT ||<>--o{ EMPLOYEE : contains
|
||||||
PROJECT <>.. TASK : manages
|
PROJECT o{<>..o{ TASK : manages
|
||||||
TEAM <> MEMBER : consists_of
|
TEAM ||<>--|| MEMBER : consists_of
|
||||||
|
COMPANY ||<>--o{ DEPARTMENT : owns
|
||||||
```
|
```
|
||||||
|
|
||||||
In these examples:
|
In these examples:
|
||||||
|
|
||||||
- `DEPARTMENT <> EMPLOYEE` shows that a department contains employees (aggregation)
|
- `DEPARTMENT ||<>--o{ EMPLOYEE` shows that one department contains zero or more employees (solid aggregation)
|
||||||
- `PROJECT <>.. TASK` shows that a project manages tasks (dashed aggregation)
|
- `PROJECT o{<>..o{ TASK` shows that zero or more projects manage zero or more tasks (dashed aggregation)
|
||||||
- `TEAM <> MEMBER` shows that a team consists of members (aggregation)
|
- `TEAM ||<>--|| MEMBER` shows that one team consists of one member (solid aggregation)
|
||||||
|
- `COMPANY ||<>--o{ DEPARTMENT` shows that one company owns zero or more departments (solid aggregation)
|
||||||
|
|
||||||
**Aggregation vs Association**
|
**Aggregation vs Association**
|
||||||
|
|
||||||
- **Aggregation** (`<>`): "Has-a" relationship where parts can exist independently
|
- **Aggregation** (`<>`): "Has-a" relationship where parts can exist independently. The aggregation marker must be combined with cardinalities and line type (e.g., `||<>--o{`)
|
||||||
- **Association** (`||--`, `}o--`): General relationship between entities
|
- **Association** (`||--`, `}o--`): General relationship between entities with cardinality markers directly connected to line type
|
||||||
|
|
||||||
|
**Additional Examples:**
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
erDiagram
|
||||||
|
UNIVERSITY ||<>--o{ COLLEGE : "has multiple"
|
||||||
|
MANAGER o|<>..o| TEAM : leads
|
||||||
|
PERSON o|<>--o| PASSPORT : owns
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
erDiagram
|
||||||
|
UNIVERSITY ||<>--o{ COLLEGE : "has multiple"
|
||||||
|
MANAGER o|<>..o| TEAM : leads
|
||||||
|
PERSON o|<>--o| PASSPORT : owns
|
||||||
|
```
|
||||||
|
|
||||||
### Attributes
|
### Attributes
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ o\| return 'ZERO_OR_ONE';
|
|||||||
o\{ return 'ZERO_OR_MORE';
|
o\{ return 'ZERO_OR_MORE';
|
||||||
\|\{ return 'ONE_OR_MORE';
|
\|\{ return 'ONE_OR_MORE';
|
||||||
u(?=[\.\-\|]) return 'MD_PARENT';
|
u(?=[\.\-\|]) return 'MD_PARENT';
|
||||||
"<>.." return 'AGGREGATION_DASHED';
|
|
||||||
"<>" return 'AGGREGATION';
|
"<>" return 'AGGREGATION';
|
||||||
\.\. return 'NON_IDENTIFYING';
|
\.\. return 'NON_IDENTIFYING';
|
||||||
\-\- return 'IDENTIFYING';
|
\-\- return 'IDENTIFYING';
|
||||||
@@ -202,18 +201,7 @@ statement
|
|||||||
yy.addRelationship($1, $7, $3, $2);
|
yy.addRelationship($1, $7, $3, $2);
|
||||||
yy.setClass([$3], $5);
|
yy.setClass([$3], $5);
|
||||||
}
|
}
|
||||||
| entityName 'AGGREGATION' entityName COLON role
|
|
||||||
{
|
|
||||||
yy.addEntity($1);
|
|
||||||
yy.addEntity($3);
|
|
||||||
yy.addRelationship($1, $5, $3, { cardA: 'ZERO_OR_MORE', relType: 'AGGREGATION', cardB: 'ZERO_OR_MORE' });
|
|
||||||
}
|
|
||||||
| entityName 'AGGREGATION_DASHED' entityName COLON role
|
|
||||||
{
|
|
||||||
yy.addEntity($1);
|
|
||||||
yy.addEntity($3);
|
|
||||||
yy.addRelationship($1, $5, $3, { cardA: 'ZERO_OR_MORE', relType: 'AGGREGATION_DASHED', cardB: 'ZERO_OR_MORE' });
|
|
||||||
}
|
|
||||||
|
|
||||||
| title title_value { $$=$2.trim();yy.setAccTitle($$); }
|
| title title_value { $$=$2.trim();yy.setAccTitle($$); }
|
||||||
| acc_title acc_title_value { $$=$2.trim();yy.setAccTitle($$); }
|
| acc_title acc_title_value { $$=$2.trim();yy.setAccTitle($$); }
|
||||||
@@ -324,13 +312,13 @@ relSpec
|
|||||||
;
|
;
|
||||||
|
|
||||||
aggregationRelSpec
|
aggregationRelSpec
|
||||||
: 'AGGREGATION' cardinality cardinality
|
: cardinality 'AGGREGATION' 'IDENTIFYING' cardinality
|
||||||
{
|
{
|
||||||
$$ = { cardA: $2, relType: $1, cardB: $3 };
|
$$ = { cardA: $1, relType: yy.Aggregation.AGGREGATION, cardB: $4 };
|
||||||
}
|
}
|
||||||
| 'AGGREGATION_DASHED' cardinality cardinality
|
| cardinality 'AGGREGATION' 'NON_IDENTIFYING' cardinality
|
||||||
{
|
{
|
||||||
$$ = { cardA: $2, relType: $1, cardB: $3 };
|
$$ = { cardA: $1, relType: yy.Aggregation.AGGREGATION_DASHED, cardB: $4 };
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -345,8 +333,6 @@ cardinality
|
|||||||
relType
|
relType
|
||||||
: 'NON_IDENTIFYING' { $$ = yy.Identification.NON_IDENTIFYING; }
|
: 'NON_IDENTIFYING' { $$ = yy.Identification.NON_IDENTIFYING; }
|
||||||
| 'IDENTIFYING' { $$ = yy.Identification.IDENTIFYING; }
|
| 'IDENTIFYING' { $$ = yy.Identification.IDENTIFYING; }
|
||||||
| 'AGGREGATION' { $$ = yy.Aggregation.AGGREGATION; }
|
|
||||||
| 'AGGREGATION_DASHED' { $$ = yy.Aggregation.AGGREGATION_DASHED; }
|
|
||||||
;
|
;
|
||||||
|
|
||||||
role
|
role
|
||||||
|
|||||||
@@ -1089,8 +1089,8 @@ describe('when parsing ER diagram it...', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('aggregation relationships', function () {
|
describe('aggregation relationships', function () {
|
||||||
it('should parse basic aggregation syntax', function () {
|
it('should parse basic aggregation syntax with solid line', function () {
|
||||||
erDiagram.parser.parse('erDiagram\nDEPARTMENT <> EMPLOYEE : contains');
|
erDiagram.parser.parse('erDiagram\nDEPARTMENT o{<>--o{ EMPLOYEE : contains');
|
||||||
const rels = erDb.getRelationships();
|
const rels = erDb.getRelationships();
|
||||||
expect(erDb.getEntities().size).toBe(2);
|
expect(erDb.getEntities().size).toBe(2);
|
||||||
expect(rels.length).toBe(1);
|
expect(rels.length).toBe(1);
|
||||||
@@ -1101,7 +1101,7 @@ describe('when parsing ER diagram it...', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should parse dashed aggregation syntax', function () {
|
it('should parse dashed aggregation syntax', function () {
|
||||||
erDiagram.parser.parse('erDiagram\nPROJECT <>.. TASK : manages');
|
erDiagram.parser.parse('erDiagram\nPROJECT o{<>..o{ TASK : manages');
|
||||||
const rels = erDb.getRelationships();
|
const rels = erDb.getRelationships();
|
||||||
expect(erDb.getEntities().size).toBe(2);
|
expect(erDb.getEntities().size).toBe(2);
|
||||||
expect(rels.length).toBe(1);
|
expect(rels.length).toBe(1);
|
||||||
@@ -1112,7 +1112,7 @@ describe('when parsing ER diagram it...', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should parse aggregation with quoted labels', function () {
|
it('should parse aggregation with quoted labels', function () {
|
||||||
erDiagram.parser.parse('erDiagram\nUNIVERSITY <> COLLEGE : "has multiple"');
|
erDiagram.parser.parse('erDiagram\nUNIVERSITY ||<>--|| COLLEGE : "has multiple"');
|
||||||
const rels = erDb.getRelationships();
|
const rels = erDb.getRelationships();
|
||||||
expect(erDb.getEntities().size).toBe(2);
|
expect(erDb.getEntities().size).toBe(2);
|
||||||
expect(rels.length).toBe(1);
|
expect(rels.length).toBe(1);
|
||||||
@@ -1122,7 +1122,7 @@ describe('when parsing ER diagram it...', function () {
|
|||||||
|
|
||||||
it('should parse multiple aggregation relationships', function () {
|
it('should parse multiple aggregation relationships', function () {
|
||||||
erDiagram.parser.parse(
|
erDiagram.parser.parse(
|
||||||
'erDiagram\nDEPARTMENT <> EMPLOYEE : contains\nPROJECT <>.. TASK : manages'
|
'erDiagram\nDEPARTMENT o{<>--o{ EMPLOYEE : contains\nPROJECT o{<>..o{ TASK : manages'
|
||||||
);
|
);
|
||||||
const rels = erDb.getRelationships();
|
const rels = erDb.getRelationships();
|
||||||
expect(erDb.getEntities().size).toBe(4);
|
expect(erDb.getEntities().size).toBe(4);
|
||||||
@@ -1132,7 +1132,7 @@ describe('when parsing ER diagram it...', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should parse aggregation with entity aliases', function () {
|
it('should parse aggregation with entity aliases', function () {
|
||||||
erDiagram.parser.parse('erDiagram\nd[DEPARTMENT]\ne[EMPLOYEE]\nd <> e : contains');
|
erDiagram.parser.parse('erDiagram\nd[DEPARTMENT]\ne[EMPLOYEE]\nd ||<>--|| e : contains');
|
||||||
const rels = erDb.getRelationships();
|
const rels = erDb.getRelationships();
|
||||||
expect(erDb.getEntities().size).toBe(2);
|
expect(erDb.getEntities().size).toBe(2);
|
||||||
expect(rels.length).toBe(1);
|
expect(rels.length).toBe(1);
|
||||||
@@ -1142,14 +1142,14 @@ describe('when parsing ER diagram it...', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should validate aggregation relationships', function () {
|
it('should validate aggregation relationships', function () {
|
||||||
erDiagram.parser.parse('erDiagram\nDEPARTMENT <> EMPLOYEE : contains');
|
erDiagram.parser.parse('erDiagram\nDEPARTMENT ||<>--|| EMPLOYEE : contains');
|
||||||
const rels = erDb.getRelationships();
|
const rels = erDb.getRelationships();
|
||||||
expect(erDb.validateAggregationRelationship(rels[0].relSpec)).toBe(true);
|
expect(erDb.validateAggregationRelationship(rels[0].relSpec)).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle mixed relationship types', function () {
|
it('should handle mixed relationship types', function () {
|
||||||
erDiagram.parser.parse(
|
erDiagram.parser.parse(
|
||||||
'erDiagram\nCUSTOMER ||--o{ ORDER : places\nPRODUCT <> ORDER_ITEM : "aggregated in"'
|
'erDiagram\nCUSTOMER ||--o{ ORDER : places\nPRODUCT ||<>--|| ORDER_ITEM : "aggregated in"'
|
||||||
);
|
);
|
||||||
const rels = erDb.getRelationships();
|
const rels = erDb.getRelationships();
|
||||||
expect(erDb.getEntities().size).toBe(4);
|
expect(erDb.getEntities().size).toBe(4);
|
||||||
@@ -1157,5 +1157,25 @@ describe('when parsing ER diagram it...', function () {
|
|||||||
expect(rels[0].relSpec.relType).toBe(erDb.Identification.IDENTIFYING);
|
expect(rels[0].relSpec.relType).toBe(erDb.Identification.IDENTIFYING);
|
||||||
expect(rels[1].relSpec.relType).toBe(erDb.Aggregation.AGGREGATION);
|
expect(rels[1].relSpec.relType).toBe(erDb.Aggregation.AGGREGATION);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should parse aggregation with different cardinalities', function () {
|
||||||
|
erDiagram.parser.parse('erDiagram\nCOMPANY ||<>--o{ DEPARTMENT : has');
|
||||||
|
const rels = erDb.getRelationships();
|
||||||
|
expect(erDb.getEntities().size).toBe(2);
|
||||||
|
expect(rels.length).toBe(1);
|
||||||
|
expect(rels[0].relSpec.relType).toBe(erDb.Aggregation.AGGREGATION);
|
||||||
|
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ONLY_ONE);
|
||||||
|
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ZERO_OR_MORE);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should parse aggregation with zero-or-one cardinality', function () {
|
||||||
|
erDiagram.parser.parse('erDiagram\nMANAGER o|<>..o| TEAM : leads');
|
||||||
|
const rels = erDb.getRelationships();
|
||||||
|
expect(erDb.getEntities().size).toBe(2);
|
||||||
|
expect(rels.length).toBe(1);
|
||||||
|
expect(rels[0].relSpec.relType).toBe(erDb.Aggregation.AGGREGATION_DASHED);
|
||||||
|
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ZERO_OR_ONE);
|
||||||
|
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ZERO_OR_ONE);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -155,30 +155,52 @@ erDiagram
|
|||||||
|
|
||||||
Aggregation represents a "has-a" relationship where the part can exist independently of the whole. This is different from composition, where the part cannot exist without the whole. Aggregation relationships are rendered with hollow diamond markers at the endpoints.
|
Aggregation represents a "has-a" relationship where the part can exist independently of the whole. This is different from composition, where the part cannot exist without the whole. Aggregation relationships are rendered with hollow diamond markers at the endpoints.
|
||||||
|
|
||||||
| Value | Alias for | Description |
|
Aggregation syntax follows a compositional pattern where you combine cardinality markers with the aggregation symbol (`<>`) and line type:
|
||||||
| :---: | :------------------: | ------------------------------ |
|
|
||||||
| <> | _aggregation_ | Basic aggregation (solid line) |
|
**Syntax:**
|
||||||
| <>.. | _aggregation-dashed_ | Dashed aggregation line |
|
|
||||||
|
```
|
||||||
|
<first-entity> <cardinalityA><>--<cardinalityB> <second-entity> : <relationship-label>
|
||||||
|
<first-entity> <cardinalityA><>..<cardinalityB> <second-entity> : <relationship-label>
|
||||||
|
```
|
||||||
|
|
||||||
|
Where:
|
||||||
|
|
||||||
|
- `<>` is the aggregation marker
|
||||||
|
- `--` represents a solid line (identifying relationship)
|
||||||
|
- `..` represents a dashed line (non-identifying relationship)
|
||||||
|
- Cardinality markers can be: `||` (only one), `o|` (zero or one), `o{` (zero or more), `|{` (one or more)
|
||||||
|
|
||||||
**Examples:**
|
**Examples:**
|
||||||
|
|
||||||
```mermaid-example
|
```mermaid-example
|
||||||
erDiagram
|
erDiagram
|
||||||
DEPARTMENT <> EMPLOYEE : contains
|
DEPARTMENT ||<>--o{ EMPLOYEE : contains
|
||||||
PROJECT <>.. TASK : manages
|
PROJECT o{<>..o{ TASK : manages
|
||||||
TEAM <> MEMBER : consists_of
|
TEAM ||<>--|| MEMBER : consists_of
|
||||||
|
COMPANY ||<>--o{ DEPARTMENT : owns
|
||||||
```
|
```
|
||||||
|
|
||||||
In these examples:
|
In these examples:
|
||||||
|
|
||||||
- `DEPARTMENT <> EMPLOYEE` shows that a department contains employees (aggregation)
|
- `DEPARTMENT ||<>--o{ EMPLOYEE` shows that one department contains zero or more employees (solid aggregation)
|
||||||
- `PROJECT <>.. TASK` shows that a project manages tasks (dashed aggregation)
|
- `PROJECT o{<>..o{ TASK` shows that zero or more projects manage zero or more tasks (dashed aggregation)
|
||||||
- `TEAM <> MEMBER` shows that a team consists of members (aggregation)
|
- `TEAM ||<>--|| MEMBER` shows that one team consists of one member (solid aggregation)
|
||||||
|
- `COMPANY ||<>--o{ DEPARTMENT` shows that one company owns zero or more departments (solid aggregation)
|
||||||
|
|
||||||
**Aggregation vs Association**
|
**Aggregation vs Association**
|
||||||
|
|
||||||
- **Aggregation** (`<>`): "Has-a" relationship where parts can exist independently
|
- **Aggregation** (`<>`): "Has-a" relationship where parts can exist independently. The aggregation marker must be combined with cardinalities and line type (e.g., `||<>--o{`)
|
||||||
- **Association** (`||--`, `}o--`): General relationship between entities
|
- **Association** (`||--`, `}o--`): General relationship between entities with cardinality markers directly connected to line type
|
||||||
|
|
||||||
|
**Additional Examples:**
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
erDiagram
|
||||||
|
UNIVERSITY ||<>--o{ COLLEGE : "has multiple"
|
||||||
|
MANAGER o|<>..o| TEAM : leads
|
||||||
|
PERSON o|<>--o| PASSPORT : owns
|
||||||
|
```
|
||||||
|
|
||||||
### Attributes
|
### Attributes
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user