Skip to content

Instantly share code, notes, and snippets.

@craicoverflow
Last active February 21, 2020 15:34
Show Gist options
  • Save craicoverflow/7a1a5a0a8c25a319e251ef95001139ea to your computer and use it in GitHub Desktop.
Save craicoverflow/7a1a5a0a8c25a319e251ef95001139ea to your computer and use it in GitHub Desktop.

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.

Cases

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.

OneToMany

"""
@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
}

Output

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'

OneToOne

"""
@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'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment