באמצעות Firebase Data Connect אפשר ליצור מחברים למכונות PostgreSQL שמנוהלות באמצעות Google Cloud SQL. המחברים האלה הם שילובים של שאילתות ושינויים לשימוש בנתונים מהסכימה.
במדריך לתחילת העבודה הוצגה סכימה של אפליקציית ביקורת על סרטים ל-PostgreSQL.
במדריך הזה הוצגו גם פעולות אדמיניסטרטיביות שניתן לפרוס ופעולות אדמיניסטרטיביות אד-הוק, כולל שינויים.
- מוטציות שאפשר לפרוס הן מוטציות שמטמיעים כדי לבצע קריאה מאפליקציות לקוח במחבר, עם נקודות קצה של API שאתם מגדירים. Data Connect משלב אימות והרשאה במוטציות האלה, ויוצר ערכות SDK ללקוח על סמך ה-API שלכם.
- מוטציות אדמיניסטרטיביות אד-הוק מופעלות מסביבות עם הרשאות כדי לאכלס ולנהל טבלאות. אפשר ליצור ולהפעיל אותם במסוף Firebase, מסביבות עם הרשאות באמצעות Firebase Admin SDK, ובסביבות פיתוח מקומיות באמצעות התוסף Data Connect VS Code.
במדריך הזה נסביר בפירוט על מוטציות שאפשר להטמיע.
מאפיינים של מוטציות Data Connect
Data Connect מאפשר לבצע מוטציות בסיסיות בכל הדרכים שצפויות לכם במסד נתונים של PostgreSQL:
- ביצוע פעולות CRUD
- ניהול פעולות מרובות שלבים באמצעות טרנזקציות
אבל עם התוספים של Data Connect ל-GraphQL, אפשר להטמיע מוטציות מתקדמות כדי ליצור אפליקציות מהירות ויעילות יותר:
- שימוש בערכי סקלר של מפתחות שמוחזרים על ידי פעולות רבות כדי לפשט פעולות חוזרות על רשומות
- שימוש בערכי שרת כדי לאכלס נתונים באמצעות פעולות שהשרת מספק
- אפשר להריץ שאילתות במהלך פעולות מוטציה מרובות שלבים כדי לחפש נתונים, וכך לחסוך בשורות קוד ובמסעות הלוך ושוב לשרת.
שימוש בשדות שנוצרו כדי להטמיע מוטציות
פעולות Data Connect ירחיבו קבוצה של שדות Data Connect שנוצרו באופן אוטומטי על סמך הסוגים והקשרים בין הסוגים בסכימה. השדות האלה נוצרים על ידי כלים מקומיים בכל פעם שאתם עורכים את הסכימה.
אפשר להשתמש בשדות שנוצרו כדי להטמיע שינויים, החל מיצירה, עדכון ומחיקה של רשומות נפרדות בטבלאות בודדות, ועד לעדכונים מורכבים יותר של כמה טבלאות.נניח שהסכימה מכילה סוג Movie
וסוג Actor
משויך.
Data Connect יוצר שדות של movie_insert
,
movie_update
, movie_delete
ועוד.
שינוי עם השדה
movie_insert
השדה |
בשדה הזה יוצרים סרט אחד. mutation CreateMovie($data: Movie_Data!) { movie_insert(data: $data) { key } } |
שינוי עם השדה
movie_update
השדה |
בשדה הזה מעדכנים סרט בודד לפי המפתח שלו. mutation UpdateMovie($myKey: Movie_Key!, $data: Movie_Data!) { movie_update(key: $myKey, data: $data) { key } } |
שינוי עם השדה
movie_delete
השדה |
בשדה הזה אפשר למחוק סרט יחיד לפי המפתח שלו. mutation DeleteMovie($myKey: Movie_Key!) { movie_delete(key: $myKey) { key } } |
רכיבים חיוניים של מוטציה
מוטציות של Data Connect הן מוטציות של GraphQL עם Data Connect extensions. בדומה למוטציה רגילה ב-GraphQL, אפשר להגדיר שם של פעולה ורשימה של משתני GraphQL.
Data Connect מרחיב את שאילתות GraphQL באמצעות הוראות מותאמות אישית כמו @auth
ו-@transaction
.
לכן, למוטציה הבאה יש:
- הגדרת סוג
mutation
- שם של פעולת שינוי (מוטציה)
SignUp
- ארגומנט של פעולה עם משתנה בודד
$username
- הנחיה יחידה,
@auth
- שדה אחד
user_insert
.
mutation SignUp($username: String!) @auth(level: USER) {
user_insert(data: {
id_expr: "auth.uid"
username: $username
})
}
כל ארגומנט של מוטציה דורש הצהרת סוג, סוג מובנה כמו String
, או סוג מותאם אישית שמוגדר בסכימה כמו Movie
.
כתיבה של מוטציות בסיסיות
אפשר להתחיל לכתוב מוטציות כדי ליצור, לעדכן ולמחוק רשומות בודדות מהמסד נתונים.
יצירה
נתחיל ביצירה בסיסית.
# Create a movie based on user input
mutation CreateMovie($title: String!, $releaseYear: Int!, $genre: String!, $rating: Int!) {
movie_insert(data: {
title: $title
releaseYear: $releaseYear
genre: $genre
rating: $rating
})
}
# Create a movie with default values
mutation CreateMovie2 {
movie_insert(data: {
title: "Sherlock Holmes"
releaseYear: 2009
genre: "Mystery"
rating: 5
})
}
או פעולת upsert.
# Movie upsert using combination of variables and literals
mutation UpsertMovie($title: String!) {
movie_upsert(data: {
title: $title
releaseYear: 2009
genre: "Mystery"
rating: 5
genre: "Mystery/Thriller"
})
}
ביצוע עדכונים
הנה עדכונים. מפיקים ובמאים בוודאי מקווים שהדירוגים הממוצעים האלה יהיו במגמת עלייה.
השדה movie_update
מכיל ארגומנט צפוי id
לזיהוי רשומה, ושדה data
שבו אפשר להשתמש כדי להגדיר ערכים בעדכון הזה.
mutation UpdateMovie(
$id: UUID!,
$genre: String!,
$rating: Int!,
$description: String!
) {
movie_update(id: $id,
data: {
genre: $genre
rating: $rating
description: $description
})
}
כדי לבצע כמה עדכונים, משתמשים בשדה movie_updateMany
.
# Multiple updates (increase all ratings of a genre)
mutation IncreaseRatingForGenre($genre: String!, $rating: Int!) {
movie_updateMany(
where: { genre: { eq: $genre } },
data:
{
rating: $rating
})
}
שימוש בפעולות increment, decrement, append ו-prepend עם _update
במוטציות _update
ו-_updateMany
אפשר להגדיר ערכים באופן מפורש ב-data:
, אבל לרוב עדיף להשתמש באופרטור כמו increment כדי לעדכן ערכים.
כדי לשנות את הדוגמה הקודמת לעדכון, נניח שרוצים להגדיל את דירוג הצפייה של סרט מסוים. אפשר להשתמש בתחביר rating_update
עם האופרטור inc
.
mutation UpdateMovie(
$id: UUID!,
$ratingIncrement: Int!
) {
movie_update(id: $id, data: {
rating_update: {
inc: $ratingIncrement
}
})
}
Data Connect תומך באופרטורים הבאים לעדכוני שדות:
-
inc
כדי להגדיל את סוגי הנתוניםInt
, Int64
, Float
, Date
ו-Timestamp
-
dec
כדי להקטין את סוגי הנתוניםInt
, Int64
, Float
, Date
ו-Timestamp
ברשימות, אפשר גם לעדכן ערכים בודדים או רשימות של ערכים באמצעות:
-
add
כדי להוסיף פריטים אם הם עדיין לא קיימים בסוגי הרשימות, למעט רשימות וקטוריות -
remove
כדי להסיר את כל הפריטים, אם יש כאלה, מסוגי רשימות, למעט רשימות וקטוריות -
append
כדי לצרף פריטים לסוגי רשימות, חוץ מרשימות וקטוריות -
prepend
כדי להוסיף פריטים בתחילת רשימות, חוץ מרשימות וקטורים
ביצוע מחיקות
כמובן שאפשר למחוק את נתוני הסרטים. אנשי שימור סרטים בוודאי ירצו לשמר את הסרטים הפיזיים כמה שיותר זמן.
# Delete by key
mutation DeleteMovie($id: UUID!) {
movie_delete(id: $id)
}
כאן אפשר להשתמש ב-_deleteMany
.
# Multiple deletes
mutation DeleteUnpopularMovies($minRating: Int!) {
movie_deleteMany(where: { rating: { le: $minRating } })
}
כתיבת מוטציות ביחסים
שימו לב איך משתמשים במוטציה המרומזת _upsert
ביחס.
# Create or update a one to one relation
mutation MovieMetadataUpsert($movieId: UUID!, $director: String!) {
movieMetadata_upsert(
data: { movie: { id: $movieId }, director: $director }
)
}
עיצוב סכימות למוטציות יעילות
Data Connect מספקת שתי תכונות חשובות שמאפשרות לכתוב מוטציות יעילות יותר ולחסוך פעולות הלוך ושוב.
ערכי סקלר של מפתח הם מזהי אובייקטים תמציתיים ש-Data Connect המערכת מרכיבה באופן אוטומטי משדות מפתח בסכימות. הסקלרים העיקריים מתייחסים ליעילות, ומאפשרים לכם למצוא בשיחה אחת מידע על הזהות והמבנה של הנתונים. הן שימושיות במיוחד כשרוצים לבצע פעולות עוקבות ברשומות חדשות וצריך מזהה ייחודי להעברה לפעולות עתידיות, וגם כשרוצים לגשת למפתחות יחסיים כדי לבצע פעולות נוספות ומורכבות יותר.
באמצעות ערכי שרת, אתם יכולים לאפשר לשרת למלא באופן דינמי שדות בטבלאות באמצעות ערכים מאוחסנים או ערכים שאפשר לחשב בקלות, בהתאם לביטויים מסוימים של CEL בצד השרת בארגומנט expr
. לדוגמה, אפשר להגדיר שדה עם חותמת זמן שתחול כשהשדה ייגש באמצעות הזמן שמאוחסן בבקשת פעולה, updatedAt: Timestamp!
@default(expr: "request.time")
.
כתיבת מוטציות מתקדמות: שימוש בתחביר field_expr
כדי לאפשר ל-Data Connect לספק ערכים
כמו שמוסבר במאמר בנושא ערכי סקלר ומאפייני שרת, אפשר לעצב את הסכימה כך שהשרת יאכלס ערכים בשדות נפוצים כמו id
ותאריכים בתגובה לבקשות של הלקוח.
בנוסף, אתם יכולים להשתמש בנתונים כמו מזהי משתמשים שנשלחים באובייקטים Data Connect request
מאפליקציות לקוח.
כשמטמיעים מוטציות, משתמשים בתחביר field_expr
כדי להפעיל עדכונים שנוצרו על ידי השרת או לגשת לנתונים מבקשות. לדוגמה, כדי להעביר את ההרשאה uid
ששמורה בבקשה לפעולה _upsert
, מעבירים את "auth.uid"
בשדה userId_expr
.
# Add a movie to the user's favorites list
mutation AddFavoritedMovie($movieId: UUID!) @auth(level: USER) {
favorite_movie_upsert(data: { userId_expr: "auth.uid", movieId: $movieId })
}
# Remove a movie from the user's favorites list
mutation DeleteFavoritedMovie($movieId: UUID!) @auth(level: USER) {
favorite_movie_delete(key: { userId_expr: "auth.uid", movieId: $movieId })
}
לחלופין, באפליקציה מוכרת של רשימת מטלות, כשיוצרים רשימת מטלות חדשה, אפשר להעביר את id_expr
כדי להנחות את השרת ליצור באופן אוטומטי מזהה ייחודי אוניברסלי (UUID) לרשימה.
mutation CreateTodoListWithFirstItem(
$listName: String!
) @transaction {
# Step 1
todoList_insert(data: {
id_expr: "uuidV4()", # <-- auto-generated. Or a column-level @default on `type TodoList` will also work
name: $listName,
})
}
מידע נוסף זמין במאמר הפניות לסקאלרים בקטע _Expr
סקאלרים.
כתיבת מוטציות מתקדמות: פעולות מרובות שלבים
יש הרבה מצבים שבהם כדאי לכלול כמה שדות כתיבה (כמו הוספות) במוטציה אחת. יכול להיות שתרצו גם לקרוא את מסד הנתונים במהלך ההפעלה של מוטציה כדי לחפש ולאמת נתונים קיימים לפני ביצוע פעולות כמו הוספות או עדכונים. האפשרויות האלה חוסכות פעולות של הלוך ושוב, ולכן גם חוסכות עלויות.
Data Connect מאפשרת לכם לבצע לוגיקה מורכבת במוטציות על ידי תמיכה ב:
כמה שדות לכתיבה
מספר שדות קריאה במוטציות (באמצעות מילת המפתח של השדה
query
).ההנחיה
@transaction
, שמספקת תמיכה בעסקאות שמוכרת ממסדי נתונים רלציוניים.ההנחיה
@check
, שמאפשרת להעריך את התוכן של פעולות קריאה באמצעות ביטויי CEL, ובהתאם לתוצאות ההערכה:- המשך ביצירה, בעדכון ובמחיקה שמוגדרים על ידי מוטציה
- המשך להחזרת התוצאות של שדה שאילתה
- שימוש בהודעות שהוחזרו כדי להפעיל לוגיקה מתאימה בקוד הלקוח
ההנחיה
@redact
, שמאפשרת להשמיט תוצאות של שדה שאילתה מתוצאות של פרוטוקול קווי.הקישור
response
של CEL, שבו מאוחסנות התוצאות המצטברות של כל השינויים והשאילתות שבוצעו בפעולה מורכבת עם כמה שלבים. אפשר לגשת לקישורresponse
:- בהנחיות
@check
, באמצעות הארגומנטexpr:
- עם ערכי שרת, באמצעות תחביר
field_expr
- בהנחיות
ההוראה @transaction
התמיכה במוטציות מרובות שלבים כוללת טיפול בשגיאות באמצעות טרנזקציות.
ההנחיה @transaction
מבטיחה שמוטציה – עם שדה כתיבה יחיד (לדוגמה, _insert
או _update
) או עם שדות כתיבה מרובים – תמיד תפעל בעסקה במסד נתונים.
מוטציות ללא
@transaction
מפעילות כל שדה בסיס אחד אחרי השני ברצף. הפעולה מציגה שגיאות כשגיאות חלקיות בשדה, אבל לא את ההשפעות של ההרצות הבאות.מוטציות עם
@transaction
מובטחות להצליח באופן מלא או להיכשל באופן מלא. אם אחד מהשדות בעסקה נכשל, העסקה כולה מבוטלת.
ההוראות @check
ו-@redact
ההנחיה @check
מאמתת שהשדות שצוינו מופיעים בתוצאות השאילתה. ביטוי של Common Expression Language (CEL) משמש לבדיקת ערכי שדות. ההתנהגות שמוגדרת כברירת מחדל של ההוראה היא לבדוק אם הערך של הצמתים הוא null
או []
(רשימות ריקות) ולדחות אותם.
ההנחיה @redact
מצנזרת חלק מהתשובה של הלקוח. השדות שצונזרו עדיין נבדקים כדי לזהות תופעות לוואי (כולל שינויים בנתונים ו@check
), והתוצאות עדיין זמינות לשלבים מאוחרים יותר בביטויים של CEL.
שימוש ב-@check
, ב-@check(message:)
וב-@redact
אחד השימושים העיקריים ב-@check
וב-@redact
הוא חיפוש נתונים קשורים כדי להחליט אם לאשר פעולות מסוימות, באמצעות חיפוש בלוגיקה אבל הסתרה שלו מהלקוחות. השאילתה יכולה להחזיר הודעות שימושיות לטיפול נכון בקוד הלקוח.
לדוגמה, בשדה השאילתה הבא נבדק אם למבקש יש תפקיד מתאים של 'אדמין' כדי להציג משתמשים שיכולים לערוך סרט.
query GetMovieEditors($movieId: UUID!) @auth(level: USER) {
moviePermission(key: { movieId: $movieId, userId_expr: "auth.uid" }) @redact {
role @check(expr: "this == 'admin'", message: "You must be an admin to view all editors of a movie.")
}
moviePermissions(where: { movieId: { eq: $movieId }, role: { eq: "editor" } }) {
user {
id
username
}
}
}
מידע נוסף על ההוראות @check
ו-@redact
בבדיקות הרשאות זמין בדיון על חיפוש נתוני הרשאות.
שימוש ב-@check
לאימות מפתחות
חלק משדות המוטציה, כמו _update
, לא יפעלו אם רשומה עם מפתח שצוין לא קיימת. באופן דומה, יכול להיות שחיפושים יחזירו ערך null או רשימה ריקה. הן לא נחשבות לשגיאות ולכן לא יפעילו חזרה לגרסה הקודמת.
כדי למנוע את התוצאה הזו, צריך לבדוק אם אפשר למצוא מפתחות באמצעות ההוראה @check
.
# Delete by key, error if not found
mutation MustDeleteMovie($id: UUID!) @transaction {
movie_delete(id: $id) @check(expr: "this != null", message: "Movie not found, therefore nothing is deleted")
}
שימוש בקישור response
כדי לשרשר מוטציות מרובות שלבים
הגישה הבסיסית ליצירת רשומות קשורות, למשל רשומת Movie
חדשה ורשומת MovieMetadata
משויכת, היא:
- קריאה למוטציה
_insert
בשבילMovie
- שמירת המפתח שמוחזר של הסרט שנוצר
- לאחר מכן, קוראים למוטציה שנייה
_insert
כדי ליצור את רשומתMovieMetadata
.
אבל עם Data Connect, אפשר לטפל במקרה הנפוץ הזה בפעולה אחת מרובת שלבים, על ידי גישה לתוצאות של _insert
הראשון ב_insert
השני.
כדי ליצור אפליקציה מוצלחת לביקורת סרטים צריך להשקיע הרבה עבודה. נשתמש בדוגמה חדשה כדי לעקוב אחרי רשימת המשימות שלנו.
שימוש ב-response
להגדרת שדות עם ערכים של השרת
במוטציה הבאה של רשימת המשימות לביצוע:
- הקישור
response
מייצג את אובייקט התשובה החלקית עד עכשיו, שכולל את כל שדות המוטציה ברמה העליונה לפני השדה הנוכחי. - הגישה לתוצאות של פעולת
todoList_insert
הראשונית, שמחזירה את השדהid
(מפתח), מתבצעת בשלב מאוחר יותר ב-response.todoList_insert.id
כדי שנוכל להוסיף מיד פריט חדש לרשימת המשימות.
mutation CreateTodoListWithFirstItem(
$listName: String!,
$itemContent: String!
) @transaction {
# Sub-step 1:
todoList_insert(data: {
id_expr: "uuidV4()", # <-- auto-generated. Or a column-level @default on `type TodoList` will also work
name: $listName,
})
# Sub-step 2:
todo_insert(data: {
listId_expr: "response.todoList_insert.id" # <-- Grab the newly generated ID from the partial response so far.
content: $itemContent,
})
}
שימוש ב-response
כדי לאמת שדות באמצעות @check
response
זמין גם ב-@check(expr: "...")
, כך שאפשר להשתמש בו כדי ליצור לוגיקה מורכבת יותר בצד השרת. בשילוב עם query { … }
שלבים במוטציות, אפשר להשיג הרבה יותר בלי לבצע עוד נסיעות הלוך ושוב בין הלקוח לשרת.
בדוגמה הבאה, שימו לב: ל-@check
כבר יש גישה ל-response.query
כי @check
תמיד פועל אחרי השלב שהוא מצורף אליו.
mutation CreateTodoInNamedList(
$listName: String!,
$itemContent: String!
) @transaction {
# Sub-step 1: Look up List.id by its name
query
@check(expr: "response.query.todoLists.size() > 0", message: "No such TodoList with the name!")
@check(expr: "response.query.todoLists.size() < 2", message: "Ambiguous listName!") {
todoLists(where: { name: $listName }) {
id
}
}
# Sub-step 2:
todo_insert(data: {
listId_expr: "response.todoLists[0].id" # <-- Now we have the parent list ID to insert to
content: $itemContent,
})
}
מידע נוסף על הקישור response
זמין במאמר בנושא CEL.
הסבר על פעולות שהופסקו באמצעות @transaction
ו-query @check
יכולות להיות שגיאות במוטציות מרובות שלבים:
- יכול להיות שפעולות במסד הנתונים ייכשלו.
- הלוגיקה של השאילתה
@check
עשויה להפסיק את הפעולות.
Data Connect ממליצה להשתמש בהנחיית @transaction
עם מוטציות מרובות שלבים. כך מתקבלת מסד נתונים עקבי יותר ותוצאות מוטציה שקל יותר לטפל בהן בקוד הלקוח:
- הפעולה תסתיים בשגיאה הראשונה או ב
@check
שנכשל, כך שלא צריך לנהל את הביצוע של שדות עוקבים או את ההערכה של CEL. - החזרה לאחור מתבצעת בתגובה לשגיאות במסד הנתונים או ללוגיקה של
@check
, וכתוצאה מכך מתקבל מצב עקבי של מסד הנתונים. - שגיאת ביטול תמיד מוחזרת לקוד הלקוח.
יכולים להיות תרחישי שימוש שבהם תבחרו שלא להשתמש ב-@transaction
: למשל, אם אתם צריכים תפוקה, יכולת הרחבה או זמינות גבוהות יותר, תוכלו לבחור בעקביות סופית. אבל כדי שהתוצאות יהיו זמינות, צריך לנהל את מסד הנתונים ואת קוד הלקוח:
- אם שדה אחד ייכשל בגלל פעולות במסד הנתונים, השדות הבאים ימשיכו לפעול. עם זאת, אם פעולת
@check
נכשלת, הפעולה כולה מסתיימת. - לא מתבצעים ביטולים, כלומר מצב מסד הנתונים מעורב עם עדכונים מוצלחים ועדכונים שנכשלו.
- יכול להיות שהפעולות שלכם עם
@check
יניבו תוצאות לא עקביות אם הלוגיקה של@check
משתמשת בתוצאות של פעולות קריאה או כתיבה בשלב קודם. - התוצאה שמוחזרת לקוד הלקוח תכיל שילוב מורכב יותר של תגובות הצלחה ותגובות שגיאה שצריך לטפל בהן.
הנחיות לשינויים ב-Data Connect
בנוסף להנחיות שבהן אתם משתמשים כדי להגדיר סוגים וטבלאות, Data Connect מספק את ההנחיות @auth
, @check
, @redact
ו-@transaction
כדי לשפר את התנהגות הפעולות.
הוראה | רלוונטי ל | תיאור |
---|---|---|
@auth |
שאילתות ומוטציות | הגדרת מדיניות ההרשאות לשאילתה או למוטציה. מידע נוסף זמין במדריך בנושא הרשאה ואישור. |
@check |
query שדות בפעולות מרובות שלבים |
הפונקציה מאמתת שהשדות שצוינו מופיעים בתוצאות השאילתה. ביטוי של Common Expression Language (CEL) משמש לבדיקת ערכי שדות. מידע על פעולות מרובות שלבים |
@redact |
שאילתות | מצנזר חלק מהתשובה של הלקוח. מידע על פעולות מרובות שלבים |
@transaction |
מוטציות | האפשרות הזו מבטיחה ששינוי יפעל תמיד בטרנזקציה של מסד נתונים. מידע על פעולות מרובות שלבים |
השלבים הבאים
נושאים שעשויים לעניין אותך:
- יצירת מוטציות לאפליקציות באמצעות כלים מבוססי-AI
- אישור המוטציות בהתאם למדריך ההרשאות
- קריאה למוטציות מקוד הלקוח עבור אינטרנט, iOS, Android ו-Flutter.
- ביצוע פעולות על נתונים בכמות גדולה באמצעות מוטציות