You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: www/apps/book/app/learn/fundamentals/data-models/relationships/page.mdx
+70-53Lines changed: 70 additions & 53 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -39,16 +39,19 @@ For example:
39
39
40
40
exportconst oneToOneHighlights = [
41
41
["5", "hasOne", "A user has one email."],
42
-
["10", "belongsTo", "An email belongs to a user."],
43
-
["11", `"email"`, "The relationship's name in the `User` data model."]
42
+
["6", `"user"`, "The relationship's name in the `Email` data model."],
43
+
["12", "belongsTo", "An email belongs to a user."],
44
+
["13", `"email"`, "The relationship's name in the `User` data model."]
44
45
]
45
46
46
47
```ts highlights={oneToOneHighlights}
47
48
import { model } from"@medusajs/framework/utils"
48
49
49
50
const User =model.define("user", {
50
51
id: model.id().primaryKey(),
51
-
email: model.hasOne(() =>Email),
52
+
email: model.hasOne(() =>Email, {
53
+
mappedBy: "user",
54
+
}),
52
55
})
53
56
54
57
const Email =model.define("email", {
@@ -63,15 +66,68 @@ In the example above, a user has one email, and an email belongs to one user.
63
66
64
67
The `hasOne` and `belongsTo` methods accept a function as the first parameter. The function returns the associated data model.
65
68
66
-
The `belongsTo` method also requires passing as a second parameter an object with the property `mappedBy`. Its value is the name of the relationship property in the other data model.
69
+
Both methods also accept a second parameter object with the property `mappedBy`. Its value is the name of the relationship property in the other data model.
67
70
68
71
### Optional Relationship
69
72
70
73
To make the relationship optional on the `hasOne` or `belongsTo` side, use the `nullable` method on either property as explained in [this chapter](../properties/page.mdx#make-property-optional).
71
74
75
+
### One-to-One Relationship in the Database
76
+
77
+
When you generate the migrations of data models that have a one-to-one relationship, the migration adds to the table of the data model that has the `belongsTo` property:
78
+
79
+
1. A column of the format `{relation_name}_id` to store the ID of the record of the related data model. For example, the `email` table will have a `user_id` column.
80
+
2. A foreign key on the `{relation_name}_id` column to the table of the related data model.
81
+
82
+

83
+
72
84
### One-sided One-to-One Relationship
73
85
74
-
If the one-to-one relationship is only defined on one side, pass `undefined` to the `mappedBy` property in the `belongsTo` method.
86
+
In some use cases, you may want to define a one-to-one relationship only on one side. This means that the other data model does not have a relationship property pointing to the first one.
87
+
88
+
You can do this either from the `hasOne` or the `belongsTo` side.
89
+
90
+
#### hasOne Side
91
+
92
+
By default, the foreign key column is added to the table of the data model that has the `belongsTo` property. For example, if the `Email` data model belongs to the `User` data model, then the foreign key column is added to the `email` table.
93
+
94
+
If you want to define a one-to-one relationship only on the `User` data model's side (`hasOne` side), you can do so by passing the following properties to the second parameter of the `hasOne` method:
95
+
96
+
-`foreignKey`: A boolean indicating whether the foreign key column should be added to the table of the data model.
97
+
-`mappedBy`: Set to `undefined`, since the relationship is only defined on one side.
98
+
99
+
For example:
100
+
101
+
exportconst oneToOneForeignKeyHighlights = [
102
+
["5", "hasOne", "A user has one email."],
103
+
["6", "foreignKey", "Add the foreign key column to the `user` table."],
104
+
["7", "mappedBy", "Set to `undefined` since the relationship is only defined on the `User` data model."],
105
+
]
106
+
107
+
```ts highlights={oneToOneForeignKeyHighlights}
108
+
import { model } from"@medusajs/framework/utils"
109
+
110
+
const User =model.define("user", {
111
+
id: model.id().primaryKey(),
112
+
email: model.hasOne(() =>Email, {
113
+
foreignKey: true,
114
+
mappedBy: undefined,
115
+
}),
116
+
})
117
+
118
+
const Email =model.define("email", {
119
+
id: model.id().primaryKey(),
120
+
})
121
+
```
122
+
123
+
In the example above, you add a one-to-one relationship from the `User` data model to the `Email` data model.
124
+
125
+
The foreign key column is added to the `user` table, and the `Email` data model does not have a relationship property pointing to the `User` data model.
126
+
127
+
128
+
#### belongsTo Side
129
+
130
+
To define the one-to-one relationship on the `belongsTo` side, pass `undefined` to the `mappedBy` property in the `belongsTo` method's second parameter.
When you generate the migrations of data models that have a one-to-one relationship, the migration adds to the table of the data model that has the `belongsTo` property:
100
-
101
-
1. A column of the format `{relation_name}_id` to store the ID of the record of the related data model. For example, the `email` table will have a `user_id` column.
102
-
2. A foreign key on the `{relation_name}_id` column to the table of the related data model.
153
+
In the example above, you add a one-to-one relationship from the `Email` data model to the `User` data model.
103
154
104
-

155
+
The `User` data model does not have a relationship property pointing to the `Email` data model.
105
156
106
157
---
107
158
@@ -118,16 +169,19 @@ For example:
118
169
119
170
exportconst oneToManyHighlights = [
120
171
["5", "hasMany", "A store has many products."],
121
-
["10", "belongsTo", "A product has one store."],
122
-
["11", `"products"`, "The relationship's name in the `Store` data model."]
172
+
["6", `"store"`, "The relationship's name in the `Product` data model."],
173
+
["12", "belongsTo", "A product has one store."],
174
+
["13", `"products"`, "The relationship's name in the `Store` data model."]
123
175
]
124
176
125
177
```ts highlights={oneToManyHighlights}
126
178
import { model } from"@medusajs/framework/utils"
127
179
128
180
const Store =model.define("store", {
129
181
id: model.id().primaryKey(),
130
-
products: model.hasMany(() =>Product),
182
+
products: model.hasMany(() =>Product, {
183
+
mappedBy: "store",
184
+
}),
131
185
})
132
186
133
187
const Product =model.define("product", {
@@ -165,7 +219,7 @@ For example:
165
219
166
220
exportconst manyToManyHighlights = [
167
221
["5", "manyToMany", "An order is associated with many products."],
168
-
["12", "manyToMany", "A product is associated with many orders."]
222
+
["15", "manyToMany", "A product is associated with many orders."]
169
223
]
170
224
171
225
```ts highlights={manyToManyHighlights}
@@ -278,43 +332,6 @@ The `OrderProduct` model defines, aside from the ID, the following properties:
278
332
279
333
---
280
334
281
-
## Set Relationship Name in the Other Model
282
-
283
-
The relationship property methods accept as a second parameter an object of options. The `mappedBy` property defines the name of the relationship in the other data model.
284
-
285
-
This is useful if the relationship property’s name is different from that of the associated data model.
286
-
287
-
As seen in previous examples, the `mappedBy` option is required for the `belongsTo` method.
288
-
289
-
For example:
290
-
291
-
exportconst relationNameHighlights = [
292
-
["6", `"owner"`, "The relationship's name in the `Email` data model."],
293
-
["13", `"email"`, "The relationship's name in the `User` data model."]
294
-
]
295
-
296
-
```ts highlights={relationNameHighlights}
297
-
import { model } from"@medusajs/framework/utils"
298
-
299
-
const User =model.define("user", {
300
-
id: model.id().primaryKey(),
301
-
email: model.hasOne(() =>Email, {
302
-
mappedBy: "owner",
303
-
}),
304
-
})
305
-
306
-
const Email =model.define("email", {
307
-
id: model.id().primaryKey(),
308
-
owner: model.belongsTo(() =>User, {
309
-
mappedBy: "email",
310
-
}),
311
-
})
312
-
```
313
-
314
-
In this example, you specify in the `User` data model’s relationship property that the name of the relationship in the `Email` data model is `owner`.
315
-
316
-
---
317
-
318
335
## Cascades
319
336
320
337
When an operation is performed on a data model, such as record deletion, the relationship cascade specifies what related data model records should be affected by it.
0 commit comments