DEV Community

Cover image for Data Modeling (AWS amplify, AppSync, GraphQL)
MD ARIFUL HASAN
MD ARIFUL HASAN

Posted on • Updated on

Data Modeling (AWS amplify, AppSync, GraphQL)

Before going to the data modeling we need to create the graphQL API.
Go to the link to create the graphQL API
This may looks time consuming. But if you're new to Data Modeling give it a shot. You're basic will be far more then clear.

Before start creating schema we've to know about some directives we're going to use while creating graphQL schema. And if don't have any idea about what GraphQL is then get some basic about GraphQl

Directives

@model @auth @hasOne @hasMany @belongTo @manyToMany @searchable @primaryKey and @index ....

@model

  • Store objects in DynamoDB

  • Configure CRUD resolvers

@auth

  • API authorization strategies

@hasOne, @hasMany, @manyToMany, @belongsTo

  • Create relationships between @model object types

@searchable

  • Active search and sorting at the same time from database.

@primaryKey, @index

  • Override default key property with custom data

Data Modeling

Now we're going to setup database tables using API(GraphQL)

Data types

  1. Scalar type: title, content (Contains scalar value like ID, String, Int, Float, DateTime etc.)
  2. Object type: Todo (which is a JavaScript Object)

Image description
Without @model directive, we'll not get any CRUD resolvers
Image description

1. @model

By adding @model directive we will get all the CRUD resolvers

Image description

Resolvers Description
getTodo Get one todo document using id or primaryKey
listTodo Get all todo documents
createTodo Insert one todo document
updateTodo Update one todo document using id or primaryKey
deleteTodo Delete one todo document using id or primaryKey

Image description

2. @auth

By adding @auth directive we will get the permission to use CRUD resolvers. Otherwise we might get an error about unauthorization.
Image description

createTodo, updateTodo, deleteTodo To create, update & delete a document in DB, we've to start the query with mutation

createTodo

  • id: id is auto generated
  • title: title comes from input object title field
  • content: content comes from input object content field Image description

getTodo, listTodo To get a document or all documents, the best practice is to start the query with query

getTodo

  • id: Provide id to get a document from DB.
  • title, content data will come from DB Image description

listTodos

  • id: Don't need id to get data
  • title, content & other propertise will come from DB Image description

deleteTodo

  • id: Provide id to delete match document
  • whole document object will delete from DB Image description

3. @index

By using secondary index or @index directive we can create another extra queryField

  • To use todoByTitleAndRank we've to provide title as argument in the query field
  • To use todoByRank we've to provide rank as argument in the query field

Image description
Image description

Setup relationships between models

Directive Data flow Relationship Example
@hasOne One-directional one-to-one A project "has one" team
@hasMany One-directional one-to-many A post "has many" comments
@belongsTo Bi-directional one-to-one or one-to-many A project has one team or a team belongs to a project
@ManyToMany Bi-directional many-to-many A blog has many tags and a tag has many blogs

4. @hasOne

Image description

  • One-directional : We'll get child object inside of a parent object. Below here Child object is Team and Parent object is Project
  • One-to-one : We'll get only one child inside of a parent object.

createTeam

  • teamName: Provide team name Image description

createProject

  • projectName: Provide project name
  • projectTeamId: Provide the exact same id of Team. This default field will be created and matched with the team id field & get the team data. We can override this field. Image description

listProjects

  • Team data will be found if projectTeamId === team.id.
  • We'll get team data inside of project.
  • But if we try to get project data inside of team it'll give us an error. Image description

@hasOne(fields: ["fieldName"])

  • This will override the default field (projectTeamId) by fieldName (teamID). We will not find the default field again. Image description
  • Now instead of matching projectTeamId === team.id, it is matching teamID === team.id. Image description

5. @hasMany

Image description

  • One-directional : We'll get array of child objects inside of a parent object. Below here Child object is Comment and Parent object is Post
  • One-to-many : We'll get one or more child inside of a parent object.

createPost

  • postName: Provide post title Image description

createComment

  • commentContent: Provide comment string
  • postCommentsId: Provide the exact same id of Post. This default field will be created and matched with the Post id field & get the comment data. We can override this field. Image description
  • Adding another comment Image description

listPosts

  • Comments will be found if postCommentsId === post.id
  • We'll get array of comment inside of post.
  • But if we try to get post data inside of comments it'll give us an error. Image description

@hasMany(indexName: "byPost", fields: ["id"])
postID: ID! @index(name: "byPost", sortKeyFields: ["content"]

  • This will override the default field (postCommentsId) by property of index (postID). We will not find the default field again. Image description
  • Adding post Image description
  • Adding comment 1
  • postID: Provide the exact same id of Post. This field will override the postCommentsId field and match the Post id field & get the comment data. Image description
  • Adding comment 2 Image description
  • Now instead of matching postCommentsId === post.id, it is matching postID === post.id. Image description

6. @belongsTo

Image description

  • Bi-directional : We'll get array of child objects inside of a parent object & we'll also get parent inside of. Below here Child object is Comment and Parent object is Post
  • Difference
Directive Can be found child data inside parent object Can be found parent data inside child object
@hasOne Yes No
@hasMany Yes No
@belongsTo Yes Yes
  • I'm explaining @belongsTo directive for @hasMany relation. You should try out @belongsTo directive for @hasOne relation. There is no change in creating @hasOne and @hasMany schema and data table.Just we will find parent data inside of a child object.

createPost

  • Provide postName Image description

createComment

  • Creating relation between two table by postCommentsId Image description
  • Add comment 2 Image description

listPost

  • Getting child (comments) data inside parent (post) object
  • Getting parent (post) data inside child (comments) object Image description

@hasMany(indexName: "byPost", fields: ["id"])
postID: ID! @index(name: "byPost")

  • This will override the default field (postCommentsId) by property of index (postID). We will not find the default field again. Image description createPost
  • Provide postName Image description

createComment

  • postID: Provide the exact same id of Post. This field will override the postCommentsId field and match the Post id field & get the comment data. Image description
  • Adding comment 2 Image description

listPost

  • Getting child (comments) data inside parent (post) object
  • Getting parent (post) data inside child (comments) object Image description

7. @manyToMany

Image description

  • This relation will create 3 data table.
Table get list create update delete subscription Found Data Object
Post Yes Yes Yes Yes Yes Yes Post, Tag, PostTags
Tag Yes Yes Yes Yes Yes Yes Post, Tag, PostTags
PostTags Yes Yes Yes Yes Yes Yes Post, Tag, PostTags
  • Bi-directional : We'll get one table inside of another table.

createPost

  • postName: Provide post name to create a post. Image description

create Tag

  • label: Provide label title to create a tag label. Image description

createPostTags
postID: Use to provide post object.
tagID: Use to provide tag object.
Image description

Advanced

Create multiple relationships between multiple model

Image description
Relations between models are

  • Department has one manager and many employees
  • Manager has one department and many employees
  • Employees has one department and one manager

createDepartment

  • Provide Department name in the departmentName input
  • We don't have manager and employee id. So we'll update the department later. Image description

createManager

  • Provide manager name in the managerName input
  • Provide department id in the departmentID input. Image description

createEmployee

  • Provide employee name in the employeeName input
  • Provide department id in the departmentID input.
  • Provide manager id in the managerID input.
  • And we're getting department and manager info in the Employee table Image description

updateDepartment

  • Provide selected department id in the id input
  • Provide manager id in the managerID input
  • and we're getting employee and manager info in department table. Image description

listManagers

  • And we're getting department and employee info in manager table. Image description

That's it for now. Thanks for your patience. If this blog help you please give a react.
Next blog will be about filtering...

Top comments (5)

Collapse
 
sumaiya176 profile image
Sumaiya176

Waiting for next one 🤗

Collapse
 
gybgivee profile image
Kamonchanok Foote

Thank you so much, this article is very helpful.

Collapse
 
arifulhasantotul profile image
MD ARIFUL HASAN

Welcome

Collapse
 
moh3ni profile image
Zia

Thanks,
I have a question, how to delete relations? ex. a Post has many tags, what if I want to remove a tag from a post?

Collapse
 
arifulhasantotul profile image
MD ARIFUL HASAN

1st scenario:
If you want to remove a tag from posts you have to do deleteTag mutations.
deleteTag and give the tag id. That tag will remove from all the posts it's linked to.
2nd scenario:
If you want to delete a tag from a particular post you have to do updatePost mutations.

updatePost and provide the post id, then pass an empty string in the field where you provided the tag id to link post and tag.