Schema و Type در GraphQL

Schema و Type در GraphQL

در جلسه های قبل با GraphQL و شیوه نوشتن کوئری در آن آشنا شدیم. از این جلسه و جلسات بعد قصد داریم تا با نحوه ایجاد یک سرویس GraphQL در سرور آشنا شویم. از آنجایی که می توان GraphQL را با هر زبان برنامه نویسی پیاده سازی کرد، نمی توان روی دستور یک زبان برنامه نویسی خاص متمرکز شد و از این رو، GraphQL زبان GraphQL Schema Language را معرفی می کند. این زبان همانند query language است و به ما این امکان را می دهد تا برای سرویس خود  schema بسازیم. این Schema توسط سرور تعریف می شود و در جلسات بعد مورد استفاده قرار می گیرد.

Schema:

در جلسه های قبل با نحوه نوشتن کوئری ها آشنا شدیم. کوئری زیر را در نظر بگیرید:

{
  Character {
    id
    name
  }
}

با توجه به کوئری نوشته شده می توان فهمید نتیجه ی این کوئری دارای چه فیلدهایی خواهد بود. اما چگونه GraphQL در سرور متوجه این موضوع می شود؟ در کوئری ها، می توان از چه فیلد هایی استفاده کرد . کلاینت چگونه متوجه این موضوع می شود؟ چگونه فیلدهای مختلف شناسایی شده و در خروجی نمایش داده می شود؟ نوع فیلدهای خروجی چه خواهد بود (مثلا String یا Integer یا یک آرایه)؟

سوال های بالا با ایجاد یک Schema در GraphQL پاسخ داده می شوند. هر سرویس GraphQL دارای مجموعه ای از type ها است که Schema آن ها را مشخص می کند. هر کوئری با این Schema بررسی شده و سرور نتیجه آن را باز می گرداند.

Object Type:

ساده ترین نوع type می تواند یک object باشد. به مثال زیر توجه کنید:

type Character {
  name: String
  family: String
}

در کد بالا، یک نوع به نام Character تعریف شده است. این نوع دارای دو فیلد به نام name و family است. این دو فیلد نیز از نوع String هستند (این نوع یک نوع Scalar است که در ادامه توضیح داده شده است).

Scalar Type ها:

در ساده ترین حالت هر فیلد می تواند دارای انواع Scalar باشد. مثال زیر گویای انواع type های scalar در GraphQL است:

type User {
  id: ID
  name: String
  isActive: Boolean
  rating: Int
  wallet: Float
}

          در GraphQL نوع های Scalar عبارت اند از:

  • Int: نوع عددی با اندازه 32 بیت (می تواند منفی یا مثبت باشد).
  • Float: نوع عددی شناور (می تواند مثبت یا منفی باشد).
  • String: نوع رشته ای با encode UTF-8
  • Boolean: نوع منطقی true یا false
  • ID: این نوع مانند String، serialize می شود. اما تفاوت آن در این است که مشخص می کند نوع فیلد از نوع ID است و unique است. از این نوع تنها برای خوانایی بیشتر استفاده می شود.

Argument:

هر فیلد در GraphQL می تواند دارای تعدادی argument باشد. برای تعریف argument کافی است تا مانند توابع در بیشتر زبان های برنامه نویسی آن ها را درون پرانتز تعریف کنیم. به مثال زیر دقت کنید:

type Character {
  id(characterId: ID = 1) ID;
  name: String
  family: String
}

در مثال بالا یک argument برای id تعریف شده است. همچنین برای این argument مقدار پیش فرض 1 در نظر گرفته شده است.

نوع Query و Mutation:

اکثر type ها در schema از نوع object type هستند. اما در schema دو type خاص با نام های query و mutation وجود دارد:

schema {
  query: Query
  mutation: Mutation
}

هر schema در GraphQL دارای یک نوع query است و می تواند mutation داشته یا نداشته باشد. این دو نوع مانند دیگر نوع ها هستند با این تفاوت که آن ها ورودی query ها و mutation ها را در GraphQL مشخص می کنند. به طور مثال:

type Query {
  hero: Character
  me: User
}

بنابراین با توجه به Query تعریف شده در Schema، می توان از کد زیر استفاده کرد:

query {
  hero {
    id
    name
  }
  me {
    name
  }
}

Enumeration Type ها:

Enum ها مانند انواع scalar هستند با این تفاوت که در کوئری ها تنها مجاز به استفاده از موارد تعریف شده در enum خواهیم بود. برای درک بهتر به مثال زیر توجه کنید:

enum UserType {
  ADMIN
  USER
  BOT
}
type User {
  id: ID
  name: String
  type: UserType
}

List ها و non-null ها:

Object type ها، scalar type ها و enum type ها تنها نوع هایی هستند که می توان در GraphQL استفاده کرد. اما این نوع ها تنها یک داده را در خروجی نمایش خواهند داد. برای استفاده از آرایه ای از داده ها می توان از List ها استفاده کرد. برای استفاده از آن ها کافیست به صورت زیر عمل کنید:

type User {
  id: ID!
  name: String!
  permissions: [Permission]
}

در کد بالا، فیلد permissions، آرایه ای از نوع Permission خواهد بود. همچنین اگر دقت کنید از علامت ! در فیلد id و name استفاده شده است. این بدان معناست که فیلدهای مورد نظر null نخواهند بود.

همچنین می توان از non-null ها در list ها نیز استفاده کرد. به مثال زیر توجه کنید:

type User {
  id: ID
  name: String
  permissions: [Permission]!
  profiles: [Profile!]
}

 اگر دقت کنید در کد بالا فیلد permissions و profiles به صورت non-null تعریف شده اند. اما در permissions، list به صورت non-null است و در فیلد profiles، اعضای لیست به صورت non-null است. این بدان معناست که برای فیلد اول هیچگاه مقدار null در خروجی چاپ نمی شود و آرایه می تواند خالی باشد. اما در فیلد دوم مقدار profiles می تواند null باشد اما هیچکدام از اعضای آرایه نمی تواند null باشد. مثال زیر برای درک بهتر این موضوع آورده شده است:

profiles: null // valid
profiles: [] // valid
profiles: ['a', 'b'] // valid
profiles: ['a', null, 'b'] // error
permissions: null // error
permissions: [] // valid
permissions: ['a', 'b'] // valid
permissions: ['a', null, 'b'] // valid

interface ها:

          همانطور که درس جلسات قبل بررسی شد، GraphQL از مفهوم interface ها پشتیبانی می کند. Type ها می توانند interface ها را پیاده سازی کنند. برای تعریف یک interface به صورت زیر عمل می کنیم:

interface Person {
  id: ID
  name: String
}

و برای استفاده از آن کافیست به صورت زیر آن را پیاده سازی کنیم:

type Admin implements Person {
  id: ID
  name: String
  profiles: [Profile]
}
 type User implements Person {
  id: ID
  name: String
  permissions: [Permission]
}

input Type ها:

اگر در جلسه های قبل دقت کرده باشید، هنگام تعریف و استفاده از یک argument، تنها مجاز به استفاده از نوع های ساده هستیم. اگر قصد استفاده از یک object به عنوان متغیر داشته باشیم باید از input type ها استفاده کنیم. برای درک بهتر، مثال زیر را در نظر بگیرید:

mutation CreateCommentForPost($postId: ID!, $comment: CommentInput!) {
  createComment(postId: $postId, comment: $comment) {
    title
    text
  }
}

در مثال بالا قصد داریم تا به عنوان ورودی comment$، از یک object به صورت زیر استفاده کنیم:

{
  "postId": "1",
  "comment": {
    "title": "comment Title",
    "text": "nice post!"
  }
}

برای این کار باید CommentInput را به صورت زیر تعریف کنیم:

input CommentInput {
  title: Int!
  text: String
}

در input type ها می توان از انواع scalar type ها و دیگر input type ها استفاده کرد. اما باید دقت کنید نمی توان از argument ها در آن ها استفاده نمود.

در این جلسه با شیوه ی ایجاد Schema و انواع type ها در GraphQL آشنا شدیم. در جلسه بعد با استفاده از زبان برنامه نویسی nodejs اقدام به پیاده سازی یک سرویس GraphQL خواهیم کرد.

 

          سرشار از آرامش باشید.

نظرات
اگر login نکردی برامون ایمیلت رو بنویس: