סקירה כללית של שאילתות גרף
באמצעות BigQuery Graph אתם יכולים לכתוב שאילתות של תרשימים כדי להתאים דפוסים של צמתים, קצוות ונתיבים, ולעבור בין קשרים באמצעות Graph Query Language (GQL).
הדוגמאות במסמך הזה מתייחסות לתרשים בשם FinGraph, שמציג את הקשרים בין אנשים, החשבונות שבבעלותם והעברות בין חשבונות. למידע על הגדרת התרשים, ראו דוגמה ל-FinGraph.
מבנה השאילתה
שאילתת תרשים מורכבת משם התרשים, ואחריו הצהרת שאילתה לינארית אחת או יותר. כל שאילתה לינארית מכילה הצהרה אחת או יותר, שמאפשרת לעבוד עם נתוני תרשים כדי למצוא התאמות לדפוסים, להגדיר משתנים, לסנן ולשנות נתוני ביניים ולהחזיר תוצאות. מריצים שאילתת תרשים באותו אופן שבו מריצים שאילתת SQL ב-BigQuery.
התאמת תבניות בגרפים
התאמת דפוסים בתרשים מוצאת דפוסים ספציפיים בתרשים. התבניות הבסיסיות ביותר הן תבניות של רכיבים, כמו תבניות של צמתים שתואמות לצמתים ותבניות של קצוות שתואמות לקצוות.
תבניות של צמתים
תבנית צומת תואמת לצמתים בתרשים. התבנית הזו מכילה סוגריים תואמים, שיכולים לכלול משתנה של תבנית גרף, ביטוי תווית ומסנני מאפיינים.
למצוא את כל הצמתים
השאילתה הבאה מחזירה את כל הצמתים בתרשים. המשתנה n, משתנה של תבנית תרשים, נקשר לצמתים התואמים. במקרה כזה, תבנית הצומת תואמת לכל הצמתים בתרשים.
GRAPH graph_db.FinGraph
MATCH (n)
RETURN LABELS(n) AS label, n.id;
השאילתה הזו מחזירה את label ו-id:
label |
id |
|---|---|
Account |
7 |
Account |
16 |
Account |
20 |
Person |
1 |
Person |
2 |
Person |
3 |
חיפוש כל הצמתים עם תווית ספציפית
השאילתה הבאה תואמת לכל הצמתים בתרשים שיש להם את התווית Person.
השאילתה מחזירה את התווית וכמה מאפיינים של הצמתים התואמים.
GRAPH graph_db.FinGraph
MATCH (p:Person)
RETURN LABELS(p) AS label, p.id, p.name;
השאילתה הזו מחזירה את המאפיינים הבאים של הצמתים התואמים:
label |
id |
name |
|---|---|---|
Person |
1 |
Alex |
Person |
2 |
Dana |
Person |
3 |
Lee |
חיפוש כל הצמתים שתואמים לביטוי של תווית
אפשר ליצור ביטוי תווית עם אופרטור לוגי אחד או יותר. לדוגמה, השאילתה הבאה תואמת לכל הצמתים בתרשים שיש להם את התווית Person או Account. המשתנה n של תבנית התרשים חושף את כל המאפיינים מצמתים עם התווית Person או Account.
GRAPH graph_db.FinGraph
MATCH (n:Person|Account)
RETURN LABELS(n) AS label, n.id, n.birthday, n.create_time;
שימו לב לפרטים הבאים בתוצאות של השאילתה הזו:
- לכל הצמתים יש את המאפיין
id. - לצמתים שתואמים לתווית
Accountיש את המאפייןcreate_timeאבל אין להם את המאפייןbirthday. המאפייןbirthdayהואNULLבצמתים האלה. - לצמתים שתואמים לתווית
Personיש את המאפייןbirthdayאבל אין להם את המאפייןcreate_time. המאפייןcreate_timeהואNULLבצמתים האלה.
label |
id |
birthday |
create_time |
|---|---|---|---|
Account |
7 |
NULL |
2020-01-10T14:22:20.222Z |
Account |
16 |
NULL |
2020-01-28T01:55:09.206Z |
Account |
20 |
NULL |
2020-02-18T13:44:20.655Z |
Person |
1 |
1991-12-21T08:00:00Z |
NULL |
Person |
2 |
1980-10-31T08:00:00Z |
NULL |
Person |
3 |
1986-12-07T08:00:00Z |
NULL |
חיפוש כל הצמתים שתואמים לביטוי התווית ולמסנן המאפיינים
השאילתה הבאה תואמת לכל הצמתים בתרשים עם התווית Person והמאפיין id ששווה ל-1:
GRAPH graph_db.FinGraph
MATCH (p:Person {id: 1})
RETURN LABELS(p) AS label, p.id, p.name, p.birthday;
התוצאה אמורה להיראות כך:
label |
id |
name |
birthday |
|---|---|---|---|
Person |
1 |
Alex |
1991-12-21T08:00:00Z |
אפשר להשתמש בסעיף WHERE כדי ליצור תנאי סינון מורכבים יותר בתוויות ובמאפיינים.
השאילתה הבאה משתמשת בסעיף WHERE כדי לסנן צמתים שבהם המאפיין birthday הוא לפני 1990-01-10:
GRAPH graph_db.FinGraph
MATCH (p:Person WHERE p.birthday < '1990-01-10')
RETURN LABELS(p) AS label, p.name, p.birthday;
התוצאה אמורה להיראות כך:
label |
name |
birthday |
|---|---|---|
Person |
Dana |
1980-10-31T08:00:00Z |
Person |
Lee |
1986-12-07T08:00:00Z |
תבניות קצה
תבנית קשתות תואמת לקשתות או לקשרים בין צמתים. תבניות קצוות מוקפות בסוגריים מרובעים ([]) וכוללות סמלים כמו -, -> או <- כדי לציין כיוונים. תבנית קשת יכולה לכלול משתנה של תבנית גרף כדי לקשר לקשתות תואמות.
חיפוש כל הקצוות עם תוויות תואמות
השאילתה הזו מחזירה את כל הקצוות בתרשים עם התווית Transfers. השאילתה מקשרת את משתנה תבנית התרשים e לקצוות התואמים.
GRAPH graph_db.FinGraph
MATCH -[e:Transfers]->
RETURN e.Id as src_account, e.order_number;
התוצאה אמורה להיראות כך:
src_account |
order_number |
|---|---|
7 |
304330008004315 |
7 |
304120005529714 |
16 |
103650009791820 |
20 |
304120005529714 |
20 |
302290001255747 |
חיפוש כל הקצוות שתואמים לביטוי התווית ולמסנן המאפיינים
תבנית הקצה בשאילתה הבאה משתמשת בביטוי תווית ובמסנן מאפיינים כדי למצוא את כל הקצוות עם התווית Transfers שתואמים למספר הזמנה מסוים:
GRAPH graph_db.FinGraph
MATCH -[e:Transfers {order_number: "304120005529714"}]->
RETURN e.Id AS src_account, e.order_number;
התוצאה אמורה להיראות כך:
src_account |
order_number |
|---|---|
7 |
304120005529714 |
20 |
304120005529714 |
חיפוש כל הקצוות באמצעות כל דפוס של קצה כיוון
אפשר להשתמש בתבנית הקצה any direction (-[]-) בשאילתה כדי להתאים קצוות בכל כיוון. השאילתה הבאה מוצאת את כל ההעברות עם חשבון חסום:
GRAPH graph_db.FinGraph
MATCH (account:Account)-[transfer:Transfers]-(:Account {is_blocked:true})
RETURN transfer.order_number, transfer.amount;
התוצאה אמורה להיראות כך:
order_number |
amount |
|---|---|
304330008004315 |
300 |
304120005529714 |
100 |
103650009791820 |
300 |
302290001255747 |
200 |
תבניות נתיבים
תבנית נתיב מורכבת מתבניות של צמתים וקצוות לסירוגין.
חיפוש כל הנתיבים מצומת ספציפי באמצעות תבנית נתיב
השאילתה הבאה מוצאת את כל ההעברות לחשבון שהתחילו מחשבון שבבעלות Person, כאשר id שווה ל-2.
כל תוצאה תואמת מייצגת נתיב מצומת Person כאשר id שווה ל-2 דרך צומת Account מחובר באמצעות קצה Owns, לצומת Account אחר באמצעות קצה Transfers.
GRAPH graph_db.FinGraph
MATCH
(p:Person {id: 2})-[:Owns]->(account:Account)-[t:Transfers]->
(to_account:Account)
RETURN
p.id AS sender_id, account.id AS from_id, to_account.id AS to_id;
התוצאה אמורה להיראות כך:
sender_id |
from_id |
to_id |
|---|---|---|
2 |
20 |
7 |
2 |
20 |
16 |
תבניות נתיבים כמותיות
תבנית מכומתת חוזרת על תבנית בטווח מסוים.
התאמה של תבנית קצה מכומתת
כדי למצוא נתיבים באורך משתנה, אפשר להחיל כַּמָּת על תבנית קצה. השאילתה הבאה מדגימה את זה על ידי חיפוש חשבונות יעד שנמצאים במרחק של העברה אחת עד שלוש העברות ממקור Account עם ערך id של 7.
השאילתה מחילה את הכַּמָּת {1, 3} על תבנית הקצה -[e:Transfers]->. ההוראה הזו מנחה את השאילתה להתאים נתיבים שחוזרים על תבנית הקצה Transfers פעם אחת, פעמיים או שלוש פעמים. הסעיף WHERE משמש להחרגת חשבון המקור מהתוצאות. הפונקציה ARRAY_LENGTH משמשת כדי לגשת אל group variable e.
GRAPH graph_db.FinGraph
MATCH (src:Account {id: 7})-[e:Transfers]->{1, 3}(dst:Account)
WHERE src != dst
RETURN src.id AS src_account_id, ARRAY_LENGTH(e) AS path_length, dst.id AS dst_account_id;
התוצאה אמורה להיראות כך:
src_account_id |
path_length |
dst_account_id |
|---|---|---|
7 |
1 |
16 |
7 |
1 |
16 |
7 |
3 |
16 |
7 |
3 |
16 |
7 |
2 |
20 |
7 |
2 |
20 |
חלק מהשורות בתוצאות חוזרות על עצמן. הסיבה לכך היא שיכולים להיות כמה נתיבים שתואמים לתבנית בין אותם צומתי מקור ויעד, והשאילתה מחזירה את כולם.
התאמה לתבנית נתיב עם כמות
השאילתה הבאה מוצאת נתיבים בין צומתי Account עם קשת אחת או שתיים של Transfers דרך חשבונות ביניים חסומים.
תבנית הנתיב בסוגריים מכומתת, והסעיף WHERE שלה מציין תנאים לתבנית החוזרת.
GRAPH graph_db.FinGraph
MATCH
(src:Account)
((a:Account)-[:Transfers]->(b:Account {is_blocked:true}) WHERE a != b){1,2}
-[:Transfers]->(dst:Account)
RETURN src.id AS src_account_id, dst.id AS dst_account_id;
התוצאה אמורה להיראות כך:
src_account_id |
dst_account_id |
|---|---|
7 |
20 |
7 |
20 |
20 |
20 |
משתני קבוצה
משתנה של תבנית גרף שמוצהר בתבנית מכומתת הופך למשתנה קבוצתי כשניגשים אליו מחוץ לתבנית הזו. לאחר מכן הוא נקשר למערך של רכיבי תרשים תואמים.
אפשר לגשת למשתנה קבוצתי כמערך. רכיבי התרשים נשמרים לפי סדר ההופעה שלהם בנתיבים התואמים. אתם יכולים לצבור משתנה קבוצתי באמצעות צבירה אופקית.
משתנה של קבוצת גישה
בדוגמה הבאה, הגישה למשתנה e מתבצעת באופן הבא:
- כמשתנה של תבנית גרף שקשור לקצה אחד בסעיף
WHEREe.amount > 100כשהוא נמצא בתוך התבנית הכמותית. - כמשתנה קבוצה שקשור למערך של רכיבי קצה ב-
ARRAY_LENGTH(e)בהצהרהRETURNכשהוא מחוץ לתבנית הכמותית. - כמשתנה קבוצתי שקשור למערך של רכיבי קצה, שנצבר על ידי
SUM(e.amount)מחוץ לתבנית הכמותית. זו דוגמה לצבירה אופקית.
GRAPH graph_db.FinGraph
MATCH
(src:Account {id: 7})-[e:Transfers WHERE e.amount > 100]->{0,2}
(dst:Account)
WHERE src.id != dst.id
LET total_amount = SUM(e.amount)
RETURN
src.id AS src_account_id, ARRAY_LENGTH(e) AS path_length,
total_amount, dst.id AS dst_account_id;
התוצאה אמורה להיראות כך:
src_account_id |
path_length |
total_amount |
dst_account_id |
|---|---|---|---|
7 |
1 |
300 |
16 |
7 |
2 |
600 |
20 |
קידומות לחיפוש נתיבים
כדי להגביל את הנתיבים התואמים בתוך קבוצות שחולקות צומתי מקור ויעד, אפשר להשתמש בקידומת החיפוש של הנתיב ANY, ANY SHORTEST או ANY CHEAPEST.
אפשר להחיל את הקידומות האלה רק לפני תבנית נתיב שלמה, ואי אפשר להחיל אותן בתוך סוגריים.
התאמה באמצעות ANY
השאילתה הבאה מוצאת את כל החשבונות הייחודיים שאפשר להגיע אליהם, שנמצאים במרחק של Transfers אחד או שניים מצומת Account נתון.
הקידומת ANY לחיפוש נתיב מבטיחה שהשאילתה תחזיר רק נתיב אחד בין זוג ייחודי של צומתי src ו-dst ב-Account. בדוגמה הבאה, למרות שאפשר להגיע לצומת Account עם {id: 16} בשני נתיבים שונים מצומת המקור Account, השאילתה מחזירה רק נתיב אחד.
GRAPH graph_db.FinGraph
MATCH ANY (src:Account {id: 7})-[e:Transfers]->{1,2}(dst:Account)
LET ids_in_path = ARRAY_CONCAT(ARRAY_AGG(e.Id), [dst.Id])
RETURN src.id AS src_account_id, dst.id AS dst_account_id, ids_in_path;
התוצאה אמורה להיראות כך:
src_account_id |
dst_account_id |
ids_in_path |
|---|---|---|
7 |
16 |
7,16 |
7 |
20 |
7,16,20 |
התאמה באמצעות ANY SHORTEST
הקידומת ANY SHORTEST לחיפוש נתיבים מחזירה נתיב אחד לכל זוג של צומתי מקור ויעד, שנבחר מבין אלה עם המספר המינימלי של קצוות.
לדוגמה, השאילתה הבאה מוצאת את אחד הנתיבים הקצרים ביותר בין צומת Account עם ערך id של 7 לבין צומת Account עם ערך id של 20. השאילתה מתייחסת לנתיבים עם קצה אחד עד שלושה קצוות של Transfers.
GRAPH graph_db.FinGraph
MATCH ANY SHORTEST (src:Account {id: 7})-[e:Transfers]->{1, 3}(dst:Account {id: 20})
RETURN src.id AS src_account_id, dst.id AS dst_account_id, ARRAY_LENGTH(e) AS path_length;
התוצאה אמורה להיראות כך:
src_account_id |
dst_account_id |
path_length |
|---|---|---|
7 |
20 |
2 |
התאמה באמצעות ANY CHEAPEST
הקידומת ANY CHEAPEST לחיפוש נתיבים מבטיחה שלכל זוג של חשבונות מקור וחשבון יעד, השאילתה תחזיר רק נתיב אחד עם עלות המחשוב הכוללת המינימלית.
השאילתה הבאה מוצאת נתיב עם עלות המחשוב הכוללת המינימלית בין צומתי Account. העלות הזו מבוססת על סכום המאפיין amount של הקצוות Transfers. החיפוש מתייחס לנתיבים עם קצה אחד עד שלושה קצוות של Transfers.
GRAPH graph_db.FinGraph
MATCH ANY CHEAPEST (src:Account)-[e:Transfers COST e.amount]->{1,3}(dst:Account)
LET total_cost = sum(e.amount)
RETURN src.id AS src_account_id, dst.id AS dst_account_id, total_cost;
התוצאה אמורה להיראות כך:
src_account_id |
dst_account_id |
total_cost |
|---|---|---|
7 |
7 |
900 |
7 |
16 |
100 |
7 |
20 |
400 |
16 |
7 |
800 |
16 |
16 |
500 |
16 |
20 |
300 |
20 |
7 |
500 |
20 |
16 |
200 |
20 |
20 |
500 |
תבניות של תרשימים
תבנית גרף מורכבת מתבנית נתיב אחת או יותר, שמופרדות באמצעות פסיק (,). תבניות גרף יכולות להכיל סעיף WHERE, שמאפשר לגשת לכל משתני תבנית הגרף בתבניות הנתיב כדי ליצור תנאי סינון. כל תבנית נתיב יוצרת אוסף של נתיבים.
התאמה באמצעות תבנית גרף
השאילתה הבאה מזהה חשבונות מתווכים ואת הבעלים שלהם שמעורבים בעסקאות בסכומים של יותר מ-200, שדרכם מועברים כספים מחשבון מקור לחשבון חסום.
תבניות הנתיבים הבאות יוצרות את תבנית התרשים:
- התבנית הראשונה מוצאת נתיבים שבהם ההעברה מתבצעת מחשבון אחד לחשבון חסום באמצעות חשבון ביניים.
- התבנית השנייה מוצאת נתיבים מחשבון לאדם שבבעלותו החשבון.
המשתנה interm משמש כקישור משותף בין שתי תבניות הנתיב, ולכן interm צריך להפנות לאותו צומת רכיב בשתי תבניות הנתיב. כך נוצרת פעולת equi-join שמבוססת על המשתנה interm.
GRAPH graph_db.FinGraph
MATCH
(src:Account)-[t1:Transfers]->(interm:Account)-[t2:Transfers]->(dst:Account),
(interm)<-[:Owns]-(p:Person)
WHERE dst.is_blocked = TRUE AND t1.amount > 200 AND t2.amount > 200
RETURN
src.id AS src_account_id, dst.id AS dst_account_id,
interm.id AS interm_account_id, p.id AS owner_id;
התוצאה אמורה להיראות כך:
src_account_id |
dst_account_id |
interm_account_id |
owner_id |
|---|---|---|---|
20 |
16 |
7 |
1 |
הצהרות שאילתה לינאריות
אפשר לשרשר כמה הצהרות גרף כדי ליצור הצהרת שאילתה לינארית. ההצהרות מבוצעות באותו סדר שבו הן מופיעות בשאילתה.
כל הצהרה מקבלת את הפלט מההצהרה הקודמת כקלט. הקלט ריק בהצהרה הראשונה.
הפלט של ההצהרה האחרונה הוא התוצאה הסופית.
לדוגמה, אפשר להשתמש בהצהרות של שאילתות לינאריות כדי למצוא את ההעברה המקסימלית לחשבון חסום. השאילתה הבאה מאתרת את החשבון ואת הבעלים שלו עם ההעברה הגדולה ביותר לחשבון חסום.
GRAPH graph_db.FinGraph
MATCH (src_account:Account)-[transfer:Transfers]->(dst_account:Account {is_blocked:true})
ORDER BY transfer.amount DESC
LIMIT 1
MATCH (src_account:Account)<-[owns:Owns]-(owner:Person)
RETURN src_account.id AS account_id, owner.name AS owner_name;
בטבלה הבאה מוצג התהליך הזה, עם תוצאות הביניים שמועברות בין כל הצהרה. כדי לקצר, מוצגים רק חלק מהמאפיינים.
| תדפיס | תוצאת ביניים (מקוצרת) | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
MATCH
(src_account:Account)
-[transfer:Transfers]->
(dst_account:Account {is_blocked:true})
|
|
||||||||||||
ORDER BY transfer.amount DESC |
|
||||||||||||
LIMIT 1 |
|
||||||||||||
MATCH
(src_account:Account)
<-[owns:Owns]-
(owner:Person)
|
|
||||||||||||
RETURN
src_account.id AS account_id,
owner.name AS owner_name
|
|
התוצאה אמורה להיראות כך:
| account_id | owner_name |
|---|---|
7 |
Alex |
פקודת חזרה
ההצהרה RETURN מציינת מה להחזיר מהתבניות התואמות. הוא יכול לגשת למשתנים של תבניות גרפים ולכלול ביטויים וסעיפים אחרים, כמו ORDER BY ו-GROUP BY.
ב-BigQuery Graph אי אפשר להחזיר רכיבי תרשים כתוצאות של שאילתות. כדי להחזיר את כל רכיב התרשים, משתמשים בפונקציה TO_JSON.
החזרת רכיבי תרשים כ-JSON
GRAPH graph_db.FinGraph
MATCH (n:Account {id: 7})
-- Returning a graph element in the final results is NOT allowed. Instead, use
-- the TO_JSON function or explicitly return the graph element's properties.
RETURN TO_JSON(n) AS n;
התוצאה אמורה להיראות כך:
| n |
|---|
{"identifier":"mUZpbkdyYXBoLkFjY291bnQAeJEO","kind":"node","labels":["Account"],"properties":{"create_time":"2020-01-10T14:22:20.222Z","id":7,"is_blocked":false,"nick_name":"Vacation
Fund"}} |
יצירת שאילתות גדולות יותר באמצעות מילת המפתח NEXT
אפשר לשרשר כמה הצהרות של שאילתות לינאריות של תרשים באמצעות מילת המפתח NEXT.
ההצהרה הראשונה מקבלת קלט ריק, והפלט של כל הצהרה עוקבת הופך לקלט של ההצהרה הבאה.
בדוגמה הבאה, כדי למצוא את הבעלים של החשבון עם הכי הרבה העברות נכנסות, משורשרות כמה הצהרות לינאריות של תרשים. אפשר להשתמש באותו משתנה, למשל account, כדי להתייחס לאותו רכיב בתרשים בכמה הצהרות לינאריות.
GRAPH graph_db.FinGraph
MATCH (:Account)-[:Transfers]->(account:Account)
RETURN account, COUNT(*) AS num_incoming_transfers
GROUP BY account
ORDER BY num_incoming_transfers DESC
LIMIT 1
NEXT
MATCH (account:Account)<-[:Owns]-(owner:Person)
RETURN account.id AS account_id, owner.name AS owner_name, num_incoming_transfers;
התוצאה אמורה להיראות כך:
| account_id | owner_name | num_incoming_transfers |
|---|---|---|
16 |
Lee |
3 |
אפשר גם לשלב הצהרות של שאילתות לינאריות עם אופרטורים של קבוצות.
פונקציות וביטויים
בשאילתות גרפים אפשר להשתמש בכל הפונקציות (פונקציות צבירה ופונקציות סקלריות), האופרטורים והביטויים המותנים של GoogleSQL. ב-BigQuery Graph יש גם תמיכה בפונקציות GQL ובאופרטורים של GQL שאפשר להשתמש בהם רק בשאילתות של תרשימים.
השאילתה הבאה כוללת שילוב של פונקציות ואופרטורים של GQL ו-SQL בתוך שאילתת גרף:
GRAPH graph_db.FinGraph
MATCH (person:Person)-[o:Owns]->(account:Account)
WHERE person IS SOURCE OF o
RETURN person, ARRAY_AGG(account.nick_name) AS accounts
GROUP BY person
NEXT
RETURN
LABELS(person) AS labels,
accounts,
CONCAT(person.city, ", ", person.country) AS location,
TO_JSON(person) AS person
LIMIT 1;
התוצאה אמורה להיראות כך:
| labels | חשבונות | location | אדם |
|---|---|---|---|
Person |
["Vacation Fund"] |
Adelaide, Australia |
{"identifier":"mUZpbkdyYXBoLlBlcnNvbgB4kQI=","kind":"node","labels":["Person"],"properties":{"birthday":"1991-12-21T08:00:00Z","city":"Adelaide","country":"Australia","id":1,"name":"Alex"}} |
שאילתות משנה
שאילתת משנה היא שאילתה שמוטמעת בתוך שאילתה אחרת. הכללים הבאים חלים על שאילתות משנה בתוך שאילתות תרשים:
- שאילתת משנה מוקפת בזוג סוגריים מסולסלים
{}. - שאילתת משנה מתחילה בסעיף
GRAPHכדי לציין את התרשים בהיקף. התרשים שצוין לא חייב להיות זהה לתרשים שנעשה בו שימוש בשאילתה החיצונית. - אי אפשר להצהיר שוב על משתנה של תבנית גרף שהוצהר מחוץ להיקף של שאילתת המשנה בתוך שאילתת המשנה, אבל אפשר להפנות אליו בביטויים או בפונקציות בתוך שאילתת המשנה.
משתמשים בשאילתת משנה כדי למצוא את המספר הכולל של ההעברות מכל חשבון
השאילתה הבאה ממחישה את השימוש בשאילתת המשנה VALUE. שאילתת המשנה מוקפת בסוגריים מסולסלים {} עם הקידומת של מילת המפתח VALUE. השאילתה מחזירה את המספר הכולל של ההעברות שהתחילו מחשבון.
GRAPH graph_db.FinGraph
MATCH (p:Person)-[:Owns]->(account:Account)
RETURN p.name, account.id AS account_id, VALUE {
GRAPH graph_db.FinGraph
MATCH (a:Account)-[transfer:Transfers]->(:Account)
WHERE a = account
RETURN COUNT(transfer) AS num_transfers
} AS num_transfers;
התוצאה אמורה להיראות כך:
| name | account_id | num_transfers |
|---|---|---|
Alex |
7 |
2 |
Dana |
20 |
2 |
Lee |
16 |
1 |
רשימה של ביטויי שאילתות משנה נתמכים מופיעה במאמר שאילתות משנה של BigQuery Graph.
פרמטרים של שאילתה
אתם יכולים לשלוח שאילתות ל-BigQuery Graph עם פרמטרים. למידע נוסף, קראו על התחביר ועל הרצת שאילתות עם פרמטרים.
השאילתה הבאה תואמת לצומתי Person שיש להם ערך id שתואם לפרמטר של שאילתה:
GRAPH graph_db.FinGraph
MATCH (person:Person {id: @id})
RETURN person.name;
הרצת שאילתות על תרשימים וטבלאות ביחד
אפשר לשלב שאילתות גרף ושאילתות SQL באמצעות האופרטור GRAPH_TABLE.
האופרטור GRAPH_TABLE מקבל שאילתת גרף לינארי ומחזיר את התוצאה שלה בטבלה שאפשר לשלב בשאילתת SQL. יכולת הפעולה ההדדית הזו מאפשרת להעשיר את תוצאות השאילתות בגרף בתוכן שלא שייך לגרף, ולהפך.
לדוגמה, אפשר ליצור טבלה בשם CreditReports ולהוסיף כמה דוחות אשראי, כמו בדוגמה הבאה:
CREATE TABLE graph_db.CreditReports (
person_id INT64 NOT NULL,
create_time TIMESTAMP NOT NULL,
score INT64 NOT NULL,
PRIMARY KEY (person_id, create_time) NOT ENFORCED
);
INSERT INTO graph_db.CreditReports (person_id, create_time, score)
VALUES
(1,"2020-01-10 06:22:20.222", 700),
(2,"2020-02-10 06:22:20.222", 800),
(3,"2020-03-10 06:22:20.222", 750);
בשלב הבא, אתם יכולים לזהות אנשים ספציפיים באמצעות התאמת דפוסים בגרף ב-GRAPH_TABLE, ולצרף את תוצאות השאילתה בגרף לטבלה CreditReports כדי לאחזר את דירוגי האשראי.
SELECT
gt.person.id,
credit.score AS latest_credit_score
FROM GRAPH_TABLE(
graph_db.FinGraph
MATCH (person:Person)-[:Owns]->(:Account)-[:Transfers]->(account:Account {is_blocked:true})
RETURN DISTINCT person
) AS gt
JOIN graph_db.CreditReports AS credit
ON gt.person.id = credit.person_id
ORDER BY credit.create_time;
התוצאה אמורה להיראות כך:
| person_id | latest_credit_score |
|---|---|
1 |
700 |
2 |
800 |
שיטות מומלצות
כדי לשפר את ביצועי השאילתות, אתם יכולים לבנות את שאילתות ה-GQL כך שיצמצמו את כמות הנתונים שנסרקים ואת מספר תוצאות הביניים.
התחלת מעבר בנתיב מצמתים בעלי עוצמה נמוכה
כדי לשמור על קבוצות קטנות של תוצאות ביניים ולהאיץ את ביצוע השאילתות, כדאי לכתוב את שאילתות התרשים כך ש-Path traversal יתחיל מצמתים עם עוצמה נמוכה יותר, בלי קשר לכיוון של ה-Path traversal. בהצהרת ה-MATCH הבאה נעשה שימוש במסנני מאפיינים כדי לצמצם את מספר הצמתים ההתחלתיים האפשריים, במקום לחשב את כל ההתאמות ואז לסנן:
MATCH (p:Person {id: 10})-[own:Owns]->(a:Account)
זה חשוב במיוחד לשאילתות של נתיבים מכומתים:
MATCH (p:Person {id: 10})-[own:Owns]->{1,3}(a:Account)
שימוש במעבר בין נתיבים כיווניים
הסכימות של BigQuery Graph הן כיווניות, כלומר לכל קשת יש צומת מקור וצומת יעד. למרות שתחביר השאילתה של התרשים מאפשר מעבר בנתיב בכל כיוון (לדוגמה, -[edge]-), מומלץ להשתמש במעבר בנתיב כיווני (לדוגמה, -[edge]-> או <-[edge]-) כדי לשפר את הביצועים. מעבר בנתיב בכל כיוון עלול לגרום לפגיעה בביצועים.
ההצהרה הבאה של MATCH משלבת שתי תנועות כיווניות עם UNION ALL:
MATCH (a1:Account {id: 7})-[t:Transfers]->(a2:Account)
...
UNION ALL
...
MATCH (a1:Account {id: 7})<-[t:Transfers]-(a2:Account)
שימוש בתחביר ANY או ANY SHORTEST לבדיקות קישוריות
שאילתות של נתיבים מכומתים יכולות להחזיר נתיבים כפולים בין צומתי מקור לצומתי יעד. אם המטרה שלכם היא לבדוק את הקישוריות ואתם לא צריכים את כל הנתיבים האפשריים, השתמשו ב-ANY או ב-ANY SHORTEST כדי לצמצם חישובים מיותרים ולשפר את היעילות של חיפוש הנתיבים. לדוגמה, בהצהרת MATCH הבאה נעשה שימוש ב-ANY SHORTEST כדי לשמור רק נתיב אחד בין כל זוג צמתים:
MATCH ANY SHORTEST (a1:Account)-[t:Transfers]->{1,3}(a2:Account)
ציון תוויות באופן מפורש
אם משמיטים תוויות של צמתים או קצוות בשאילתה, BigQuery Graph מונה את כל התוויות של הצמתים והקצוות שעומדות בתנאים. הספירה הזו עלולה לגרום לסריקה של יותר תוויות מהנדרש. כדי למנוע את זה, כדאי לציין תוויות לכל הצמתים והקצוות בשאילתה, כשאפשר.
לדוגמה, בשאילתה הבאה מצוינות התוויות Account ו-Transfers:
GRAPH graph_db.FinGraph
MATCH (a1:Account)-[t:Transfers]->(a2:Account)
RETURN COUNT(*) AS num_transfers;
כדאי להימנע מהשמטת תוויות, כי זה עלול לגרום לסריקה של קשרים אחרים לא נחוצים בין צמתים. בשאילתה הבאה, a1 יכול לייצג חשבון או אדם, ו-t יכול לייצג העברה או בעלות על חשבון.
GRAPH graph_db.FinGraph
MATCH (a1)-[t]->(a2)
RETURN COUNT(*) AS num_transfers;
שימוש בהצהרת MATCH אחת
ב-BigQuery Graph אפשר לכלול כמה הצהרות MATCH בשאילתת תרשים אחת. ההצהרות האלה מקושרות באמצעות משתנים שהוצהרו כמה פעמים ומייצגים את אותו צומת או קצה. עם זאת, שימוש בכמה הצהרות MATCH יכול להפחית את היתרונות של עוצמה בין הצהרות. כדי לשפר את הביצועים, מומלץ להשתמש בהצהרת MATCH אחת.
לדוגמה, השאילתות הבאות זהות, אבל הראשונה פועלת טוב יותר כי היא משתמשת בהצהרת MATCH אחת:
-- Preferred syntax.
GRAPH graph_db.FinGraph
MATCH
(p:Person {id: 1})-[o:Owns]->
(a:Account)-[t:Transfers]->(a2:Account)
RETURN o.account_id, t.amount;
-- Avoid this syntax.
GRAPH graph_db.FinGraph
MATCH (p:Person {id: 1})-[o:Owns]->(a:Account)
MATCH (a:Account)-[t:Transfers]->(a2:Account)
RETURN o.account_id, t.amount;
הגבלת הקצוות שעוברים דרך צמתים עם עוצמה גבוהה
כששולחים שאילתות לתרשימים, יכול להיות שלצמתים מסוימים יהיה מספר גדול משמעותית של קצוות נכנסים או יוצאים בהשוואה לצמתים אחרים. הצמתים האלה עם עוצמה גבוהה נקראים לפעמים צומתי-על או צומתי רכזת. צומתי-על יכולים לגרום לבעיות בביצועים, כי מעבר דרכם עשוי לכלול עיבוד של כמויות גדולות של נתונים, מה שמוביל לחלוקת נתונים לא מאוזנת (partition skew) ולזמני ביצוע ארוכים.
כדי לבצע אופטימיזציה של שאילתה בתרשים עם צומתי-על, משתמשים בפונקציה ROW_NUMBER() בתוך משפט FILTER או משפט WHERE ב-MATCH כדי להגביל את מספר הקצוות שהשאילתה עוברת מצומת או אליו. השיטה הזו שימושית במיוחד כשלא צריך פירוט מלא של כל החיבורים מצומת-על או אליו.
לדוגמה, אם בחלק מהחשבונות ב-FinGraph יש מספר גדול של עסקאות, אפשר להשתמש ב-ROW_NUMBER() כדי להגביל את מספר הקצוות של Transfers שצריך להביא בחשבון לכל Account, וכך להימנע משאילתה לא יעילה:
GRAPH graph_db.FinGraph
MATCH (a1:Account)-[e1:Transfers WHERE e1 IN {
GRAPH graph_db.FinGraph
-- Sample 5 edges per source node
MATCH -[selected_e:Transfers]->
FILTER ROW_NUMBER() OVER (
PARTITION BY SOURCE_NODE_ID(selected_e)) < 5
RETURN selected_e
}]->{1,3}(a2:Account)
RETURN COUNT(*) AS cnt;
דגימת צמתים או קצוות ביניים בשאילתות עם כמה דילוגים
כדי לשפר את יעילות השאילתות, אפשר להשתמש ב-ROW_NUMBER() כדי לדגום צמתים ביניים בשאילתות עם כמה דילוגים. השיטה הזו מגבילה את מספר הנתיבים שהשאילתה בוחנת לכל צומת ביניים. כדי לעשות את זה, צריך לפצל שאילתה עם כמה דילוגים לכמה הצהרות MATCH שמופרדות באמצעות NEXT, ולהחיל את ROW_NUMBER() בנקודת האמצע שבה רוצים לדגום:
GRAPH graph_db.FinGraph
MATCH (a1:Account)-[e1:Transfers]->(a2:Account)
-- Sample 5 destination nodes per a1 source node
FILTER ROW_NUMBER() OVER (PARTITION BY ELEMENT_ID(a1)) < 5
RETURN a1, a2
NEXT
MATCH (a2)-[e2:Transfers]->(a3:Account)
RETURN a1.id AS src_id, a2.id AS mid_id, a3.id AS dst_id;