Let's Learn AdonisJS 5 #5.6

Defining Model Relationships

In this lesson, we'll learn how to define relationships on our Lucid Models. We'll cover one-to-one, many-to-one, one-to-many, and many-to-many relationship definitions.

🕑 Chapters:

00:00 - Intro
00:30 - Relationship Types
01:30 - AdonisJS Relationship Lookup
02:30 - AdonisJS Relationship Decorators
03:20 - Belongs To (one-to-one)
04:15 - Has One (one-to-one)
05:20 - Relation Configuration Options
07:00 - Belongs To (many-to-one)
07:30 - Has Many (many-to-one)
08:00 - Relationship Model Names
09:30 - Many To Many
11:20 - Pivot Table & Pivot Columns
12:30 - Outro


📜 Transcript:

0:00

so the reason that we saved

0:01

relationships in our models as one of

0:03

the last things here to Define within

0:04

our models is because they kind of work

0:06

differently from the remainder of the

0:08

columns that we've defined so far we've

0:09

defined everything that actually exists

0:11

within our database we all of these are

0:13

valid columns if we were to go look

0:14

within our database they have column

0:15

representations there the actual

0:17

relationship definitions though we're

0:18

going to serve as more of a virtual

0:19

definition and they have lookups that

0:22

look up to the particular IDs that

0:24

define those relationships and the way

0:25

that we Define these varies slightly

0:27

depending on what particular

0:28

relationship type it is so we have one

0:31

to one one to many many to one and then

0:33

many to many within our existing schema

0:35

over here on the right hand side I do

0:36

have those to find out within a key down

0:38

at the bottom I'm going to go ahead and

0:39

expand this out so on the lines pointing

0:41

to the specific relationship definitions

0:43

I've marked it as one to one for one to

0:45

one one to M for one to many M to one

0:48

for minute one and then M to M for many

0:49

to many now the difference between one

0:51

to many and many to one differs

0:52

depending on what side of the

0:54

relationship you're looking on so I've

0:55

pointed all of these in the same

0:57

direction so that all of our one to many

0:59

and many to one are defined as the same

1:01

so here you can see we have a role ID

1:04

pointing to our roles table from our

1:06

users table that's defined as M to 1 as

1:09

many to one instead of one to many

1:10

whereas if we were to go the other way

1:12

then that would become a one to many so

1:14

in terms of those two it's just

1:15

depending on what side of the

1:17

relationship you're starting from and

1:18

pointing to similar to how I have this

1:20

key noting out the different

1:21

relationship pipes here we also need to

1:23

do the exact same thing within our model

1:25

to tell Adonis what type of relationship

1:27

it is that we're working with so that

1:29

they know how to look it up accordingly

1:30

so let's go and collapse this down and

1:32

just like with the actual columns how

1:34

it's differed from camel case to snake

1:36

case there are specific lookups that

1:38

Adonis is going to look for as the

1:40

default naming convention within our

1:41

profile column here we have this user ID

1:43

now the way Adonis is going to look this

1:46

user ID relationship up by default

1:48

whenever we actually Define this

1:49

relationship is this going to take the

1:50

relationship model name and then it's

1:52

going to take the primary key for that

1:53

model and snake case it together so it's

1:56

going to be user underscore ID that it

1:58

would look for because the user model is

2:00

the model that that column is relating

2:02

to and ID is the primary key so here we

2:05

have a match with the actual default

2:06

naming convention for Adonis so the way

2:08

that we would Define this is if we look

2:10

over at our key this is a one-to-one

2:12

relationship our users are always going

2:14

to have one profile and our profiles are

2:16

always going to belong to one user so in

2:19

terms of our Lucid models we're going to

2:20

want to Define both sides of those

2:22

relationships so that we have both sides

2:23

to work with you can Define just one

2:25

side if you know that there's one side

2:26

you're never going to work with but I

2:29

prefer to Define both because you never

2:31

know when it might come in handy later

2:32

down the road and the way that we Define

2:33

these relationships just like with all

2:35

of our column definitions is via

2:36

decorators so there's a different

2:37

decorator per relationship type that we

2:40

have within our model in a really great

2:42

spot to find all of the different

2:43

decorators for the relationships is

2:44

within the documentation if you go into

2:46

references the database scroll down on

2:48

the left hand side you'll see

2:49

relationships here and you'll see has

2:50

one has many belongs to many to many and

2:53

then has many through now we're not

2:54

going to be focusing on as many through

2:55

quite yet we'll save that for a later

2:56

point in time but with our specific

2:58

schema we do have a relationship for

2:59

each one of these four has one has many

3:02

belongs to a many to many which one to

3:03

use here in your particular use case can

3:05

be kind of confusing for people

3:06

especially if you're not used to the

3:08

terminology here the easiest way to

3:09

remember it here if we dive back into

3:11

our profile if the column actually

3:13

exists on the model in most cases that

3:16

will be a belongs to because our profile

3:18

belongs to the specific user ID so we

3:22

can Define this within this model here

3:24

by doing at belongs to and then we

3:26

provide in the actual model that this is

3:29

related to so we do this as a callback

3:31

function let's import our user model

3:33

here then just like all of our other

3:35

columns here we want to do public give

3:37

this relationship a name we can do user

3:39

and then the type for this is going to

3:40

be belongs to let's open this up type of

3:44

and then the user so if I scroll up just

3:46

a little bit here you can see we have

3:47

our user ID on our profile model now we

3:50

also have a user relationship which

3:51

serves as kind of a virtual

3:53

representation of what a actual user Is

3:55

So within our profile model we already

3:57

have everything done this is our

3:58

perfectly valid relationship definition

4:00

all we need to do from here is query and

4:02

work with it but we do want to go on the

4:04

inverse side of this relationship on our

4:06

user and also Define it there because we

4:08

don't know whether or not we need to

4:09

populate the profile from the user side

4:10

or from the profile side so we want it

4:12

to be available from both sides so that

4:14

we can work with it either way so let's

4:15

jump over to our user model scroll down

4:17

since there's no profile ID on the

4:19

actual model here this isn't going to be

4:20

it belongs to it's going to be a has one

4:22

because a user has one profile so we can

4:24

do at as one provide this a callback of

4:27

type profile and this will point the

4:29

actual relationship to our profile model

4:30

do public profile and then we want to

4:33

define the type here as has one type of

4:35

profile and so now we have both sides of

4:37

the relationship defined so whenever we

4:39

go to query this we can query a user

4:41

with a profile or we can query a profile

4:43

with its attached user either way it

4:45

works so there's an example of a

4:47

one-to-one relationship definition

4:48

within adonisjs on one side we have a

4:51

has one and then on the other side we

4:53

have a belongs two because this is the

4:55

side that has the actual referencing of

4:57

the ID for the relationship and the way

4:58

that the Donis is going to look up up

5:00

the ID value here is based off of the

5:02

relationship definition so it's going to

5:03

take the model and it's going to lower

5:05

case that and it's going to concatenate

5:07

that with the primary key of that

5:08

related model so in this case it would

5:10

be user underscore ID and that's how it

5:12

would look up the column definition

5:13

within the actual database and the

5:15

actual column value for our user ID up

5:17

here is the exact same it's user

5:18

underscore ID so the two match up

5:20

perfectly in the case that they didn't

5:22

there is that additional option set

5:23

within this belongs to has one has many

5:26

and many to many all of them have it

5:28

they do very differently depending on

5:30

what type of relationship definition it

5:31

is but they all have this additional

5:33

option set where we could define

5:34

specific column values in case anything

5:36

doesn't match up one to one with the

5:38

default naming structure of Adonis and

5:40

again the best place to find all

5:41

different relationship options is within

5:43

the documentation within the reference

5:44

under database you can scroll on down to

5:46

decorators where you have all of the

5:48

different decorators that we have

5:49

defined here so if you look at has one

5:51

you can see right here we have our has

5:54

one example with a profile if we scroll

5:56

down we have all of the different

5:57

options that we can provide into this so

5:59

we have the foreign key the local key

6:00

serialize as and on query callbacks that

6:03

we can Define on this particular

6:04

relationship the foreign key and local

6:06

key are the two different options that

6:07

you have in this particular relationship

6:09

definition when it comes to how Donna

6:11

should look up what particular column it

6:13

should find for a particular

6:14

relationship so you have form key for

6:16

one side of the relationship and local

6:18

key for the other side of the

6:19

relationship so you can Define the two

6:20

different columns that you should use

6:21

for the relationship look up there and

6:23

then you have serialize which changes

6:25

the actual column name and how it's

6:26

serialized the same as with the column

6:28

decorator then you also have on query

6:30

which allows us to Define additional

6:32

always existing query definitions

6:34

whenever we go to query the actual

6:36

column and this is really powerful and

6:38

allows us to Define specifics if we want

6:40

to define a relationship specifically

6:42

for a set type so say maybe with our

6:44

many many relationship with our posts

6:45

and our topics if we always wanted our

6:48

topic to query public posts we could

6:51

Define that within the on query images

6:52

always happen anytime that we query our

6:54

posts from our topic cool so we have one

6:56

relationship definition done let's go

6:58

ahead and move on to some of the others

6:59

how about we do a mini to one next let's

7:01

do our user and our role so let's go

7:03

back into our user model and this is

7:05

another case where we have a specific ID

7:07

on the user model now despite this being

7:09

a many to one instead of a one to one

7:11

since the ID is still on this model it

7:13

still belongs to definition so we can

7:15

scroll down to the bottom do at belongs

7:17

to provide us a callback to our role

7:20

model public role and the type will be

7:22

belongs to type of role so there's one

7:24

side let's jump over to our role model

7:26

and on this side since a role can have

7:28

many users this would be a has many

7:30

relationship so we could do at has many

7:33

provide this a callback with the user

7:35

model since this is the relating model

7:37

do public users has many type of user

7:41

and there we go there's our many to one

7:42

relationship example done now we do have

7:43

a couple more of those within this

7:44

project so let's go ahead and Define

7:45

those out before we move on to many to

7:47

many so we also have a post that belongs

7:48

to many users so let's go ahead and

7:50

Define that out so let's jump into our

7:51

post model here again this is another

7:53

one where it has that ID on it so in

7:55

this case it's going to be belongs to so

7:57

we can scroll down to the bottom do at

7:59

belongs 2 provide that our user model

8:01

public user belongs to type of user now

8:06

in this particular use case whenever we

8:07

go to add our user onto our posts via

8:09

querying it may not make complete sense

8:11

to us what exactly the user is so it

8:13

might make more sense to name this

8:14

something different something more

8:16

meaningful for our relationship name

8:17

here so since we actually have the model

8:19

bound to the relationship the model is

8:21

what's going to be used to find that

8:22

actual column name and the actual name

8:24

of the relationship or free to name

8:26

whatever we desire so here instead of

8:28

user we're free to name this something

8:29

like author if we so wish and whenever

8:31

we go to query that later on we can use

8:33

that reference name of author in order

8:35

to preload our author onto our posts in

8:38

which case that might be more meaningful

8:39

than preloading a user onto a post

8:41

instead we can preload an author so you

8:43

have that option available to you as

8:45

well so we can go ahead and give that a

8:46

save jump over to the other side so we

8:48

have that user side and over here our

8:50

users can have many posts so this would

8:52

be a has mini so we do at has many host

8:55

public posts has many type of and there

8:59

we go there's that relationship

9:00

definition done now on our post we do

9:02

have one more additional belongs to and

9:04

that's for our state ID so we can go

9:05

ahead and Define that up as well so this

9:07

would be at belongs to state public

9:10

State belongs to type of state and we go

9:13

ahead and jump into our state model and

9:15

Define that relationship there as well a

9:17

state can have many posts so this would

9:19

be a at has many post public posts as

9:23

many type of posts there we go and now

9:27

all that that leaves us is our post to

9:28

topic many to many relationships so for

9:30

this specific relationship we do have

9:32

this post topic pivot table that we'll

9:34

want to go through in order to bind this

9:36

relationship together and if you

9:37

remember there's a specific many-to-many

9:39

decorator that allows us to do that

9:41

without needing to define a specific

9:42

model for that post user table so let's

9:44

jump into our post side first and let's

9:46

get this to find out so we have an at

9:48

many to many just like all of the others

9:51

we wanted to find this to the particular

9:52

model that is bound to on the inverse

9:55

side of the many to many skipping over

9:56

that pivot table so in this case it

9:58

would be our topic scroll up a little

10:00

bit here this would be public topics

10:01

Mini 2 mini type of topic so really

10:05

looks the exact same as all of the

10:06

others but whenever it comes to the

10:08

actual option set there is a little bit

10:09

more to it so let's dive into the

10:10

documentation set take a look at it so

10:12

you can go back within the reference

10:13

database scroll down to the orms section

10:15

where decorators is come over on this

10:17

page to many to many and you can see

10:19

each one of these options here along

10:21

with a definition so since there's two

10:22

different sides to this relationship

10:23

you're going to have two different sets

10:25

of keys you can Define so you have the

10:27

four in which is one side and then you

10:28

have the local which is the other so

10:30

pivot foreign key is going to be one

10:32

side pivot related form key is going to

10:34

be the other then you have local key and

10:36

related key which are two different

10:37

sides as well and if you ever get

10:38

confused or needed an example whenever

10:40

you're looking this up on the Fly you

10:42

can get within guides scroll down to the

10:43

orm section go underneath relationships

10:46

come over here on the right hand side

10:47

the mini the mini and you'll get an

10:49

example so here within the example you

10:50

have users and skills Bound by a skill

10:52

user pivot table if you scroll down just

10:54

a brief bit it goes over what each one

10:56

of these Keys represents with that

10:57

example so just know that that does

10:59

exist exist on the documentation if you

11:01

ever get confused on which is which

11:02

there a great way to bypass all of that

11:04

is just use the default naming

11:05

Convention of Adonis because that's what

11:07

we've done here and we can just leave

11:08

this relationship definition as is and

11:10

everything will work out of the box with

11:12

no issues but if you do ever need to

11:13

provide those in here just provide a

11:15

secondary argument of those relationship

11:17

options and they'll work just fine there

11:19

are a couple of additional ones that we

11:20

haven't covered yet called pivot table

11:21

and that's going to be the table name of

11:23

the actual pivot table so in our case

11:25

it's going to be post topic and the way

11:26

that it'll find that is just binds two

11:28

model names together and snake case and

11:30

that's the default naming convention

11:31

that we've gone with here so we don't

11:32

need to Define that here but there is an

11:34

additional one of pivot columns and

11:36

these are columns that will be included

11:38

from the pivot table anytime that we

11:39

query these relationships so in our case

11:42

we do have one of those we have that

11:44

sort order and the way that we can

11:45

Finance this via an array and we just

11:47

need to define the actual column name

11:48

there to include with it so if we want

11:50

that included every single time that we

11:51

read these two relationships we want to

11:53

include that on both sides of that

11:54

relationship so that it will be

11:55

automatically included you can also omit

11:57

that here and Define to include it in

11:59

any particular one query on the query in

12:01

itself so you have the two different

12:03

options there on how to include those

12:05

intermediary table columns in our use

12:06

case I'll go ahead and leave it here so

12:08

that you know that that does exist so

12:09

let's go and jump back over to the

12:10

opposite side here so we have our post

12:12

done now we need to do our topic side

12:13

and this is just going to look the exact

12:15

same everything's just going to be flip

12:16

flop so we have our mini to mini this

12:18

will be bound to our post public posts

12:20

mini to mini type of post again we also

12:24

have all of those same options available

12:26

here everything is just flip-flop

12:27

value-wise but we do want to Define that

12:30

pivot columns as sort order so that's

12:33

available anytime that we query and

12:34

there we have it so all of our

12:35

relationship definitions are done we're

12:37

good to move on to crud work in the next

12:39

lesson if you enjoyed this lesson or you

12:41

learned something new please consider

12:42

hitting the like button down below and

12:44

subscribing future lessons just like

12:45

this one as I just stated we're going to

12:47

move on to credward next with our

12:49

different models and then we'll move

12:51

into relationship cred work after that

12:52

so thanks for sticking around everybody

12:54

I'll see you all in the next one

12:57

[Music]

Join The Discussion! (0 Comments)

Please sign in or sign up for free to join in on the dicussion.