הסופר בחר ב־קרן קוד פתוח וחינמית לקבלת תרומה כחלק מתוכנית כתיבה בעבור תרומות.
הקדמה
GraphQL הוא פתרון מודרני לקידום תקשורת בין חזית העבודה למקור נתונים. כל הפרטים והיכולות של יישום GraphQL מוסכמים ב־סכימת GraphQL. כדי לכתוב סכימת GraphQL פועלת, עליכם להבין את מערכת הסוגים של GraphQL.
במאמר זה, תלמדו על סוגי GraphQL: הסוגים הסקלריים המובנים החמישה, האנומים, סוגי העטיפה רשימה ולא-ריק, סוגי Object, והסוגים המופשטים ממשק ו־איחוד שעובדים בצידם. תסקור דוגמאות לכל סוג ותלמד כיצד להשתמש בהם כדי לבנות סכימה של GraphQL מושלמת.
דרישות מוקדמות
כדי להשיג את המרב מהמדריך הזה, יש לך צורך ב:
- הבנה של העקרונות הבסיסיים של GraphQL, שמובאים ב־מבוא ל־GraphQL.
- A GraphQL environment, an example of which can be found in How to Set Up a GraphQL API Server in Node.js.
סוגי סקאלר
כל הנתונים בסכימת GraphQL סופית מתמצאים בסופית סוגי סקאלר שונים, שמייצגים ערכים פרימיטיביים. תגובות GraphQL יכולות להיות מיוצגות כעץ, והסוגי סקאלר הם העלים בסופו של העץ. יכולים להיות הרבה רמות בתגובה מקוננת, אך הרמה האחרונה תמיד תפתור לסוג סקאלר (או Enum). GraphQL מגיע עם חמישה סוגי סקאלר מובנים: Int
, Float
, String
, Boolean
ו־ID
.
Int
Int
הוא ערך מספרי חשבוני חיובי או שלילי בגודל של 32 ביטים ללא פרקונים. זהו מספר שלם שחיובי או שלילי ואינו כולל ספרות עשרוניות. הערך המרבי של מספר שלם חתום ב-32 ביטים הוא 2,147,483,647
. זהו אחד משני הסקאלרים המובנים המשמשים לנתונים מספריים.
Float
A Float
is a signed double-precision fractional value. It is a signed (positive or negative) number that contains a decimal point, such as 1.2
. This is the other built-in scalar used for numerical data.
String
A String
is a UTF-8 character sequence. The String
type is used for any textual data. This can also include data like very large numbers. Most custom scalars will be types of string data.
Boolean
A Boolean
is a true
or false
value.
ID
ערך ID
הוא זיהוי ייחודי. ערך זה תמיד מתואר כמחרוזת, גם אם ה-ID
הוא מספרי. סוג ה-ID
יכול להיות מיוצג באופן נפוץ בעזרת מזהה ייחודי לכל היקף (UUID).
סקלרים מותאמים אישית
בנוסף לסקלרים המובנים אלה, ניתן להשתמש במילת המפתח scalar
כדי להגדיר סקלר מותאם אישית. ניתן להשתמש בסקלרים מותאמים אישית כדי ליצור סוגים שיש להם אימות ברמת השרת נוסף, כגון Date
, Time
, או Url
. הנה דוגמה להגדרת סוג Date
חדש:
scalar Date
השרת ידע לטפל באינטראקציות עם סוג זה באמצעות GraphQLScalarType
.
סוג Enum
סוג ה-Enum, ידוע גם כסוג Enumerator, מתאר קבוצה של ערכים אפשריים.
באמצעות ערכת ה- API של משחקי הדמיון מהתמכרים אחרים בסדרה כיצד לנהל נתונים עם GraphQL, ניתן ליצור enum
עבור תפקידי הגיבורים במשחק וסוגי היצורים עם כל הערכים שהמערכת תקבל עבורם. Enum מוגדר עם מילת המפתח enum
, כך:
"The job class of the character."
enum Job {
FIGHTER
WIZARD
}
"The species or ancestry of the character."
enum Species {
HUMAN
ELF
DWARF
}
בכך, הוא מובטח שהערך של Job
של דמות הוא FIGHTER
או WIZARD
ולא יכול להיות בטעות "אדום"
או מחרוזת אקראית אחרת, שיכולה לקרות אם היית משתמש בסוג String
במקום ליצור Enum מותאם אישית. Enums כתובים באותיות גדולות לפי המסורת.
Enums יכולים גם לשמש כערכים מקובלים בארגומנטים. לדוגמה, תוכל ליצור Enum של Hand
כדי לציין האם נשק הוא יד יחידה (כמו חרב קצרה) או יד כפולה (כמו אקס כבד), ולהשתמש בזה כדי לקבוע אם ניתן לצייד עם יד אחת או שתיים:
enum Hand {
SINGLE
DOUBLE
}
"A valiant weapon wielded by a fighter."
type Weapon {
name: String!
attack: Int
range: Int
hand: Hand
}
type Query {
weapons(hand: Hand = SINGLE): [Weapon]
}
ה-Enum Hand
הוכרז עם ערכים SINGLE
ו-DOUBLE
, והארגומנט בשדה weapons
מכיל ברירת מחדל של SINGLE
, שפירושו אם אין ארגומנט שמועבר אז הוא יחזור ל-SINGLE
.
סוג Non-Null
תוכל לשים לב ש-null
או undefined
, סוג שנחשב בצורה נפרדת בשפות רבות כפרימיטיבי, חסר מהרשימה של סקלרים מובנים. Null קיים ב-GraphQL ומייצג אי זמינות של ערך.
הכללים ב-GraphQL מחייבים את כל הסוגים להיות null כברירת מחדל, ולכן null
הוא תגובה חוקית לכל סוג. כדי להגדיר ערך כחובה, עליו להיות מומר לסוג Non-Null בעזרת סימן קריאה בסיומת. Non-Null מוגדר כמובן, אשר הם סוגי שמשמשים לשנות את הסוג שהם מתייחסים אליו. לדוגמה, String
הוא מחרוזת אופציונלית (או מקובלת), ו-String!
הוא מחרוזת דרושה (או לא מקובלת).
סוג רשימה
A List type in GraphQL is another type modifier. Any type that is wrapped in square brackets ([]
) becomes a List type, which is a collection that defines the type of each item in a list.
לדוגמה, סוג שמוגדר כ-[Int]
יהיה אוסף של סוגי Int
, ו-[String]
יהיה אוסף של סוגי String
. ניתן להשתמש ביחד ב-Non-Null וברשימה כדי להגדיר סוג דרוש ומוגדר כרשימה, כמו לדוגמה [String]!
.
סוג אובייקט
אם סוגי ה-Scalar של GraphQL מתארים את "העלים" בקצה התגובה ההיררכית של GraphQL, אז סוגי Object מתארים את "הסניפים" האמצעיים, וכמעט כל דבר בסכמת GraphQL הוא סוג של Object.
עצמים מורכבים מרשימת שדות מזוהים (מפתחות) וסוג הערך שכל שדה יתקבל אליו. עצמים מוגדרים עם המילה המפתח type
. לפחות שדה אחד או יותר חייב להיות מוגדר, ושדות לא יכולים להתחיל בשני קווי תחתות (__
) כדי למנוע התנגשות עם מערכת האינטרוספקציה של GraphQL.
בדוגמת ממשק ה- API למשחקי פנטזיה ב-GraphQL, ניתן ליצור עצם Fighter
כדי לייצג סוג של דמות במשחק:
"A hero with direct combat ability and strength."
type Fighter {
id: ID!
name: String!
level: Int
active: Boolean!
}
בדוגמה זו, סוג העצם Fighter
הוגדר, ויש בו ארבעה שדות מזוהים:
id
מחזיר סוגID
לא ריק.name
מחזיר סוגString
לא ריק.level
מחזיר סוגInt
.active
מחזיר סוגBoolean
לא ריק.
מעל להגדרה, ניתן גם להוסיף הערה באמצעות גרשיים כפולים, כפי שניתן לראות בדוגמה זו: "גיבור עם יכולת קרב ישירה וכוח."
. זה יופיע כתיאור לסוג.
בדוגמה זו, כל שדה מסתיים בסוג סקלרי, אך שדות עצם יכולים גם להסתיים בסוגים עצמיים אחרים. לדוגמה, ניתן ליצור סוג Weapon
, ולהגדיר את הסכמת ה-GraphQL כך שהשדה weapon
ב-Fighter
יפתור לעצם Weapon
:
"A valiant weapon wielded by a fighter."
type Weapon {
name: String!
attack: Int
range: Int
}
"A hero with direct combat ability and strength."
type Fighter {
id: ID!
name: String!
level: Int
active: Boolean!
weapon: Weapon
}
עצמים יכולים גם להיות מקוננים בתוך השדות של עצמים אחרים.
סוגי פעולות השורש
קיימים שלושה אובייקטים מיוחדים המשמשים כנקודות כניסה לסכימת GraphQL: שאילתה, מוטציה ומינוי. אלה ידועים כסוגי פעולות השורש ועוקבים אחר כללי ההתנהגות של כל סוג אובייקט אחר.
המילה המפתח schema
מייצגת את נקודת הכניסה לסכימת GraphQL. הסוגים הראשיים של השאילתה, המוטציה והמינוי יהיו על אובייקט השורש schema
:
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
הסוג של השאילתה דרוש בכל סכימת GraphQL ומייצג בקשת קריאה, דומה לGET
ב-REST API. הנה דוגמה לאובייקט שאילתתי ראשי שמחזיר רשימה של סוגי Fighter
:
type Query {
fighters: [Fighter]
}
המוטציות מייצגות בקשת כתיבה, שתהיה דומה לPOST
, PUT
, או DELETE
ב-REST API. בדוגמה הבאה, הMutation
מכיל שדה addFighter
עם ארגומנט מזוהה (input
):
type Mutation {
addFighter(input: FighterInput): Fighter
}
לבסוף, מינוי מתאים לזרם אירועים, שייתכן וישמש בשילוב עם Websocket באפליקציה רשתית. ב-GraphQL Fantasy API, אולי יהיה ניתן להשתמש בו לפגישות קרב אקראיות, כמו כן:
type Subscription {
randomBattle(enemy: Enemy): BattleResult
}
שימו לב שנקודת הכניסה schema
לעיתים קרובות מוסתרת במימושים מסוימים של GraphQL.
ארגומנטים של שדה
שדות של אובייקט GraphQL בעצם הם פונקציות שמחזירות ערך, והן יכולות לקבל ארגומנטים דומים לכל פונקציה. ארגומנטי שדה מוגדרים על ידי שם הארגומנט ואחריו סוג הארגומנט. ארגומנטים יכולים להיות מכל סוג לא-אובייקט. בדוגמה זו, אובייקט ה־Fighter
יכול להיות מסוננת על ידי השדה id
(שמתקבלת כסוג ID
לא מאולם):
type Query {
fighter(id: ID!): Fighter
}
דוגמה זו מסוימת שימושית לקבלת פריט יחיד ממאגר הנתונים, אך ארגומנטים יכולים גם לשמש למסננים, פגינציה, ושאילתות ספציפיות נוספות.
סוג ממשק
כמו סוג האובייקט, הממשק האבסטרקטי סוג הממשק מורכב מרשימת שדות מקובעות והערכים המשויכים אליהם. ממשקים נראים ועוקבים אחר כללי המשחק כמו אובייקטים, אך משמשים להגדרת תת-מימוש של אובייקט.
עד כה בסכמתך, יש לך אובייקט Fighter
, אך ייתכן גם שתרצה ליצור Wizard
, Healer
, ואובייקטים אחרים שיש להם מספר שדות דומים אך עם כמה הבדלים. במקרה זה, ניתן להשתמש בממשק כדי להגדיר את השדות שמשותפים לכולם, וליצור אובייקטים שהם מימושים של הממשק.
בדוגמה הבאה, ניתן ליצור ממשק BaseCharacter
בעזרת המילה השמורה interface
עם כל השדות שכל סוג של דמות יהיה ברשותה:
"A hero on a quest."
interface BaseCharacter {
id: ID!
name: String!
level: Int!
species: Species
job: Job
}
לכל סוג דמות תהיה ברשותה את השדות id
, name
, level
, species
, ו־job
.
עכשיו, נניח שיש לך סוג Fighter
וסוג Wizard
שיש להם שדות משותפים אלו, אך Fighters
משתמשים ב־Weapon
ו־Wizards
משתמשים ב־Spells
. ניתן להשתמש במילת המפתח implements
כדי להבחין בכל סוג כמימוש של BaseCharacter
, מה שאומר שהם חייבים להכיל את כל השדות מהממשק שנוצר:
"A hero with direct combat ability and strength."
type Fighter implements BaseCharacter {
id: ID!
name: String!
level: Int!
species: Species
job: Job!
weapon: Weapon
}
"A hero with a variety of magical powers."
type Wizard implements BaseCharacter {
id: ID!
name: String!
level: Int!
species: Species
job: Job!
spells: [Spell]
}
Fighter
ו־Wizard
הם שניהם מימושים תקפים של הממשק BaseCharacter
מכיוון שהם מכילים את תת־הקבוצה הדרושה של השדות.
Union Type
סוג אבסטרקט נוסף שניתן להשתמש בו עם אובייקטים הוא סוג האיחוד (Union type). באמצעות מילת המפתח union
, ניתן להגדיר סוג המכיל רשימה של אובייקטים הכולם יכולים לשמש כתגובה תקפה.
על ידי שימוש בממשקים שנוצרו בקטע הקודם, ניתן ליצור סוג איחוד בשם Character
שמגדיר דמות כסוג Wizard
או Fighter
:
union Character = Wizard | Fighter
התו השווה (=
) מגדיר את ההגדרה, והתו הקו-שני (|
) פועל כהצהרה לאוֹר. שימו לב כי סוג איחוד חייב להכיל אובייקטים או ממשקים. סוגי סקאלר אינם תקפים על סוג איחוד.
כעת, אם תבקש רשימת דמויות, ניתן יהיה להשתמש בסוג האיחוד Character
ולהחזיר את כל סוגי הדמויות Wizard
ו-Fighter
.
סיכום
במדריך זה, למדת על רבים מהסוגים שמגדירים את מערכת הסוגים של GraphQL. הסוגים הבסיסיים ביותר הם הסוגים הסקלריים, שהם הערכים שמשמשים כעלים בעץ הסכמה, ומורכבים מ Int
, Float
, String
, Boolean
, ID
, וכל סוג סקלרי מותאם אישית שמימוש GraphQL יחליט ליצור. Enumerations הם רשימות של ערכי קבוע תקפים שניתן להשתמש בהם כאשר נדרשת יותר שליטה על תגובה מאשר פשוט להכריז על זה כ String
, והם גם עלים בעץ הסכמה. סוגים של רשימות ולא-ריקים מוכרים כסוגי מודיפיקציה, או סוגי עטיפה, והם יכולים להגדיר סוגים אחרים כאוספים או נדרשים, בהתאמה. אובייקטים הם הסניפים של עץ הסכמה, וכמעט כל מה שבעץ הסכמה של GraphQL הוא סוג של אובייקט, כולל את הנקודות הכניסה query
, mutation
, ו subscription
. סוגים של ממשק ואיחוד הם סוגים אבסטרקטיים שיכולים להיות מועילים בהגדרת אובייקטים.
למידה נוספת, תוכל לתרגל יצירה ושינוי של סכמת GraphQL על ידי קריאה במדריך איך להגדיר שרת API של GraphQL ב Node.js כדי לקבל סביבת שרת GraphQL פועלת.
Source:
https://www.digitalocean.com/community/conceptual-articles/understanding-the-graphql-type-system