For a flexible relationship mapping system to work, we really only need two fields, along with the relationship type:
@oneToMany | @oneToOne | @manyToOne
field: The field name on the opposite model to map to.
column: The database column name on the opposite model to map to.
The field
and column
can be optional depending on what other metadata is provided. See Cases below for some examples.
- Users could use
field
only if they do not care about the underlying database implementation. - Users can additionally specify
column
if they want to customise the database column name or map to an existing column table. column
on its own would not work as it is not mapped to GraphQL field.
✅ field
+ column
annotations exist with our without opposite field. We can generate the opposite field since we have all information about it.
✅ field
annotation exists with or without opposite field. Here we can assume the column name is ${fieldName}Id
.
❌ only column
annotation on @oneToMany
(without field
) and opposite field exists but without annotation. This is invalid because we do not know which field is associated with the custom colum name on the M:1
side.
❌ column
annotation exists and opposite field does not exist. This is invalid as we do not have enough information to know which GraphQL field to map to.
"""
@model
"""
type User {
id: ID!
"""
@oneToMany field: 'sender' column: 'sender_id'
"""
sentMessages: [Message]!
}
"""
@model
"""
type Message {
id: ID!
"""
@manyToOne field: 'sentMessages' column: 'sender_id'
"""
sender: User
}
Produces metadata:
1:M
kind: 'oneToMany'
parent: User
parentField: 'sentMessages'
mapsTo:
model: Message
field: 'sender'
column: 'sender_id'
M:1
kind: 'manyToOne'
parent: Message
parentField: 'sender'
mapsTo:
model: User
field: 'sentMessages'
column: 'sender_id'
"""
@model
"""
type User {
id: ID!
"""
@oneToOne field: 'user' column: 'user_id'
"""
userAccount: [Message]!
}
"""
@model
"""
type Account {
id: ID!
"""
@oneToOne field: 'userAccount' column: 'account_id'
"""
user: User
}
1:1 (User:Account)
kind: 'oneToOne'
parent: User
parentField: 'userAccount'
mapsTo:
model: Account
field: 'sentMessages'
column: 'user_id'
1:1 (Account:User)
kind: 'oneToOne'
parent: Account
parentField: 'user'
mapsTo:
model: User
field: 'userAccount'
column: 'user_id'