1. מבוא

פעילות שמקורה בתרמית כוללת לעיתים קרובות רשתות נסתרות של ישויות מקושרות – לדוגמה, כמה חשבונות שמשתפים את אותה כתובת אימייל, מספר טלפון או כתובת פיזית. מסדי נתונים רלציוניים מסורתיים מתקשים לבצע שאילתות ביעילות על קשרים מורכבים כאלה עם כמה שלבים.
BigQuery Graph מאפשר לכם לנתח את הרשתות האלה בקנה מידה גדול באמצעות מסדי נתונים של גרפים. אתם יכולים להגדיר גרף נכסים על גבי הטבלאות הקיימות שלכם ב-BigQuery ולהשתמש ב-Graph Query Language (GQL) כדי למצוא דפוסים בנתונים.
אחד השימושים הנפוצים ברשתות גרפים לזיהוי הונאות הוא עצירת הזמנות שכתובת המשלוח שלהן משויכת לרשת הונאות או עצירת תשלומים ששייכים ל .
ב-codelab הזה תיצרו פתרון לזיהוי הונאות באמצעות BigQuery Graph. תטעינו נתונים מ-Cloud Storage, תיצרו תרשים נכסים ותשתמשו בשאילתות תרשים כדי לזהות קשרים חשודים.
מה תלמדו
- איך יוצרים מערך נתונים ב-BigQuery וטוענים נתונים.
- איך מגדירים גרף נכסים באמצעות DDL.
- איך שולחים שאילתות לגרף באמצעות GQL.
- איך משתמשים בניתוח גרפים כדי לזהות תרמיות.
הדרישות
- פרויקט ב-Google Cloud שהחיוב בו מופעל.
- סביבת מחברת BigQuery (BigQuery Studio או Colab Enterprise).
עלות
ב-Lab הזה נעשה שימוש במשאבים של Google Cloud שחלים עליהם חיובים. העלות המשוערת היא פחות מ-5$, בהנחה שתמחקו את המשאבים אחרי שתסיימו.
2. לפני שמתחילים
בוחרים פרויקט קיים או יוצרים פרויקט חדש ב-Google Cloud.
- במסוף Google Cloud, בדף לבחירת הפרויקט בענן, בוחרים פרויקט בענן או יוצרים פרויקט בענן חדש.
- הקפידו לוודא שהחיוב מופעל בפרויקט בענן שלכם ב-Google Cloud. איך בודקים אם החיוב מופעל
בחירת הסביבה
כדי להפעיל את שיעור ה-Lab הזה, תצטרכו סביבת מחברת. אפשר להשתמש ב-BigQuery Studio או ב-Colab Enterprise.
- עוברים לדף BigQuery במסוף Google Cloud.
- תשתמשו במחברת Python כדי להריץ את שאילתות הגרף.
הפעלת Cloud Shell
- לוחצים על Activate Cloud Shell בחלק העליון של מסוף Google Cloud.
- אימות האימות:
gcloud auth list
- מאשרים את הפרויקט:
gcloud config get project
- מגדירים אותו לפי הצורך:
export PROJECT_ID=<YOUR_PROJECT_ID>
gcloud config set project $PROJECT_ID
הפעלת ממשקי ה-API
מריצים את הפקודה הבאה כדי להפעיל את BigQuery API הנדרש:
gcloud services enable bigquery.googleapis.com
3. טען נתונים
בשלב הזה תיצרו מערך נתונים ב-BigQuery ותטענו את הנתונים לדוגמה מ-Cloud Storage.
הנתונים לדוגמה מורכבים מכמה קובצי CSV שמייצגים סביבה קמעונאית מדומה:
-
customers.csv: פרטי חשבון הלקוח. emails.csv: כתובות אימייל.-
phones.csv: מספרי טלפון. -
addresses.csv: כתובות פיזיות. -
customer_emails.csv,customer_phones.csv,customer_addresses.csv: קישור טבלאות. -
orders.csv: היסטוריית הזמנות, כולל סימון של הונאות.
יצירת מערך הנתונים
יוצרים מערך נתונים בשם fraud_demo כדי לאחסן בו את הטבלאות.
- ב-codelab הזה נריץ פקודות SQL. אפשר להריץ את הפקודות האלה ב-BigQuery Studio > SQL Editor, או להשתמש בפקודה
bq queryב-Cloud Shell.
כדי לקבל חוויה טובה יותר עם הצהרות יצירה מרובות שורות, אנחנו מניחים שאתם משתמשים בעורך SQL של BigQuery.
CREATE SCHEMA IF NOT EXISTS `fraud_demo` OPTIONS(location="US");
טעינת טבלאות
מריצים את הצהרות ה-SQL הבאות כדי לטעון נתונים מ-Cloud Storage למערך הנתונים.
LOAD DATA OVERWRITE `fraud_demo.customers`
FROM FILES (
format = 'CSV',
uris = ['gs://sample-data-and-media/fraud-demo-data/customers.csv'],
skip_leading_rows = 1
);
LOAD DATA OVERWRITE `fraud_demo.emails`
FROM FILES (
format = 'CSV',
uris = ['gs://sample-data-and-media/fraud-demo-data/emails.csv'],
skip_leading_rows = 1
);
LOAD DATA OVERWRITE `fraud_demo.phones`
FROM FILES (
format = 'CSV',
uris = ['gs://sample-data-and-media/fraud-demo-data/phones.csv'],
skip_leading_rows = 1
);
LOAD DATA OVERWRITE `fraud_demo.addresses`
FROM FILES (
format = 'CSV',
uris = ['gs://sample-data-and-media/fraud-demo-data/addresses.csv'],
skip_leading_rows = 1
);
LOAD DATA OVERWRITE `fraud_demo.customer_emails`
FROM FILES (
format = 'CSV',
uris = ['gs://sample-data-and-media/fraud-demo-data/customer_emails.csv'],
skip_leading_rows = 1
);
LOAD DATA OVERWRITE `fraud_demo.customer_phones`
FROM FILES (
format = 'CSV',
uris = ['gs://sample-data-and-media/fraud-demo-data/customer_phones.csv'],
skip_leading_rows = 1
);
LOAD DATA OVERWRITE `fraud_demo.customer_addresses`
FROM FILES (
format = 'CSV',
uris = ['gs://sample-data-and-media/fraud-demo-data/customer_addresses.csv'],
skip_leading_rows = 1
);
LOAD DATA OVERWRITE `fraud_demo.orders`
FROM FILES (
format = 'CSV',
uris = ['gs://sample-data-and-media/fraud-demo-data/orders.csv'],
skip_leading_rows = 1
);
4. יצירת גרף הנכסים
אחרי שהנתונים נטענים, אפשר להגדיר את גרף הנכסים. גרף מאפיינים מורכב מצמתים (ישויות) ומקצוות (קשרים).
בשיעור ה-Lab הזה, הצמתים הם:
- לקוח: מייצג את בעל החשבון.
- טלפון: מייצג מספר טלפון.
- אימייל: מייצג כתובת אימייל.
- כתובת: מייצג כתובת פיזית.
הקצוות הם:
- OwnsPhone: מקשר בין לקוח לטלפון.
- OwnsEmail: מקשר בין לקוח לבין אימייל.
- LinkedToAddress: מקשר בין לקוח לכתובת.

יצירת הגרף
מריצים את הצהרת ה-DDL הבאה כדי ליצור את הגרף בשם FraudDemo במערך הנתונים fraud_demo.
CREATE OR REPLACE PROPERTY GRAPH fraud_demo.FraudDemo
NODE TABLES(
fraud_demo.customers
KEY(account_id)
LABEL Customer PROPERTIES(
account_id,
name),
fraud_demo.emails
KEY(email)
LABEL Email PROPERTIES(
email,
email_type),
fraud_demo.phones
KEY(phone_number)
LABEL Phone PROPERTIES(
phone_number,
phone_type),
fraud_demo.addresses
KEY(address)
LABEL Address PROPERTIES(
address,
address_type)
)
EDGE TABLES(
fraud_demo.customer_emails
KEY(account_id, email)
SOURCE KEY(account_id) REFERENCES customers(account_id)
DESTINATION KEY(email) REFERENCES emails(email)
LABEL OwnsEmail PROPERTIES(
account_id,
email,
last_updated_ts),
fraud_demo.customer_phones
KEY(account_id, phone_number)
SOURCE KEY(account_id) REFERENCES customers(account_id)
DESTINATION KEY(phone_number) REFERENCES phones(phone_number)
LABEL OwnsPhone PROPERTIES(
account_id,
phone_number,
last_updated_ts),
fraud_demo.customer_addresses
KEY(account_id, address)
SOURCE KEY(account_id) REFERENCES customers(account_id)
DESTINATION KEY(address) REFERENCES addresses(address)
LABEL LinkedToAddress PROPERTIES(
account_id,
address,
last_updated_ts)
);
5. ניתוח רשתות (2 קפיצות)
פותחים מחברת חדשה ב-BigQuery Studio.

לצורך החלקים של התצוגה החזותית וההמלצות ב-Codelab הזה, נשתמש ב-notebook של Google Colab ב-BigQuery Studio. כך אפשר לראות בקלות את תוצאות הגרף.
BigQuery Graph Notebook מיושם כ-IPython Magics. אם מוסיפים את פקודת הקסם %%bigquery עם הפונקציה TO_JSON, אפשר להמחיש את התוצאות כמו שמוצג בקטעים הבאים. בשלב הזה, מריצים שאילתת גרף כדי למצוא קשרים פשוטים בין החשבונות. זוהי שאילתה עם 2 קפיצות כי היא עוברת 2 קפיצות מחוץ לצומת התחלתי כדי למצוא צמתים קשורים (למשל, Customer -> Email -> Customer).
נתחיל בבדיקת החשבון ששייך לNicole Wade. אנחנו רוצים למצוא חשבונות שקשורים אליה דרך 2 קפיצות.
הרצת שאילתת 2-Hop
מריצים את השאילתה הבאה במחברת.
%%bigquery --graph
GRAPH fraud_demo.FraudDemo
MATCH
p=(a:Customer)
( -[e:OwnsEmail|OwnsPhone|LinkedToAddress WHERE e.last_updated_ts < '2025-07-30']- (n) ){2}
WHERE a.account_id IN ("d2f1f992-d116-41b3-955b-6c76a3352657")
-- Verify the final node in the hop array is a Customer
AND 'Customer' IN UNNEST(LABELS(n[OFFSET(1)]))
RETURN TO_JSON(p) AS paths

הסבר על התוצאות
השאילתה הזו:
- מתחיל בצומת
Customerעםaccount_id'd2f1f992-d116-41b3-955b-6c76a3352657' (Nicole Wade). - הקשתות
OwnsEmail,OwnsPhoneאוLinkedToAddressמובילות לצומת מקשר (Phone,EmailאוAddress). - עוקב אחרי הקצוות בחזרה מהצומת המקשר לצמתים אחרים מסוג
Customer. - מסננים קצוות על סמך חותמת זמן (
last_updated_ts) כדי לראות את מצב הרשת בזמן מסוים.
אפשר לראות שZachary Cordova ו-Brenda Brown מחוברים ל-Nicole דרך אותה כתובת.
6. ניתוח רשתות (4 קפיצות)
בשלב הזה, תרחיבו את השאילתה כדי למצוא קשרים מורכבים יותר. נחפש חיבורים של 4 קפיצות. כך אנחנו יכולים למצוא חשבונות שמקושרים דרך כמה ישויות ביניים (למשל: לקוח א' -> אימייל -> לקוח ב' -> טלפון -> לקוח ג').
נבחן גם את השינויים ברשת הזו לאורך זמן.
הסטטוס 'לפני'
קודם נסתכל על הרשת כפי שהיא הייתה ב-30 ביולי 2025.
מריצים את השאילתה הבאה:
%%bigquery --graph
%%bigquery --graph
MATCH p= ANY SHORTEST (a:Customer)
( -[e:OwnsEmail|OwnsPhone|LinkedToAddress WHERE e.last_updated_ts < '2025-07-30']- (n) ){3, 5}(reachable_a:Customer)
WHERE a.account_id IN ("d2f1f992-d116-41b3-955b-6c76a3352657")
-- Ensure the final node in the dynamic chain is actually a Customer
AND 'Customer' IN UNNEST(LABELS(n[OFFSET(ARRAY_LENGTH(n) - 1)]))
GRAPH fraud_demo.FraudDemo
RETURN
TO_JSON(p) AS paths, -- Array of all traversed edges
ARRAY_LENGTH(e) AS hop_count

המצב 'אחרי'
עכשיו נראה איך הרשת נראית שבועיים אחרי. נריץ את אותה שאילתה אבל בלי הגבלות התאריכים.
מריצים את השאילתה הבאה:
%%bigquery --graph
GRAPH fraud_demo.FraudDemo
MATCH p= ANY SHORTEST (a:Customer)
( -[e:OwnsEmail|OwnsPhone|LinkedToAddress]- (n) ){3, 5}(reachable_a:Customer)
WHERE a.account_id IN ("d2f1f992-d116-41b3-955b-6c76a3352657")
-- Ensure the final node in the dynamic chain is actually a Customer
AND 'Customer' IN UNNEST(LABELS(n[OFFSET(ARRAY_LENGTH(n) - 1)]))
RETURN
TO_JSON(p) AS paths, -- Array of all traversed edges
ARRAY_LENGTH(e) AS hop_count

הסבר על התוצאות
אם מסירים את מסנני התאריכים, השאילתה מופעלת על קבוצת הנתונים המלאה. תראו שהרשת גדלה באופן משמעותי. Nicole Wade היא עכשיו חלק מקבוצה גדולה ומקושרת יותר. ההתרחבות המהירה הזו של רשת מקושרת היא אינדיקטור חזק לפעילות שמקורה בתרמית, כמו רשת של נוכלים שמשתפים משאבים לאורך זמן.
7. יצירת דוח הונאה
בשלב הזה, תשלבו ניתוח גרפים עם נתונים עסקיים מסורתיים (הזמנות) כדי ליצור דוח מקיף על הונאות. תוכלו לזהות חשבונות בסיכון והזמנות שעלולות להיות הונאה.
השאילתה הזו מורכבת יותר. הוא משתמש ב-GRAPH_TABLE כדי להריץ את שאילתת הגרף ב-SQL סטנדרטי, ומחשב את השינוי בגודל הרשת (diff) בין המצבים 'לפני' ו'אחרי' שראינו בשלב הקודם.
הרצת שאילתת דוח ההונאה
מריצים את השאילתה הבאה ב-notebook.
%%bigquery --graph
WITH num_orders AS (
SELECT account_id, COUNT(1) AS num_order
FROM fraud_demo.orders
WHERE order_time > '2025-07-30'
GROUP BY account_id
),
orders AS (
SELECT account_id, order_id, fraud, order_total
FROM fraud_demo.orders
WHERE order_time > '2025-07-30'
),
-- Use Quantified Path Patterns to find connections up to 4 hops away
latest_connect AS (
SELECT
account_id,
ARRAY_LENGTH(ARRAY_AGG(DISTINCT connected_id)) AS size
FROM GRAPH_TABLE(
fraud_demo.FraudDemo
MATCH (a:Customer)-[:OwnsEmail|OwnsPhone|LinkedToAddress]-{4}(connected:Customer)
RETURN a.account_id AS account_id, connected.account_id AS connected_id
)
GROUP BY account_id
),
prev_connect AS (
SELECT
account_id,
ARRAY_LENGTH(ARRAY_AGG(DISTINCT connected_id)) AS size
FROM GRAPH_TABLE(
fraud_demo.FraudDemo
-- Apply the timestamp filter to EVERY edge in the 4-hop chain
MATCH (a:Customer)
(-[e:OwnsEmail|OwnsPhone|LinkedToAddress WHERE e.last_updated_ts < '2025-07-30']-(n)){4}
WHERE 'Customer' IN UNNEST(LABELS(n[OFFSET(3)]))
RETURN a.account_id AS account_id, n[OFFSET(3)].account_id AS connected_id
)
GROUP BY account_id
),
edge_changes AS (
SELECT account_id, MAX(last_updated_ts) AS max_last_updated_ts
FROM fraud_demo.customer_addresses
GROUP BY account_id
)
SELECT
la.account_id,
o.order_id,
la.size AS latest_size,
COALESCE(pa.size, 0) AS previous_size,
la.size - COALESCE(pa.size, 0) AS diff,
nos.num_order,
o.fraud AS reported_as_fraud,
o.order_total,
CASE
WHEN (la.size - COALESCE(pa.size, 0)) > 10 AND nos.num_order IS NULL THEN "CUSTOMER AT RISK"
WHEN (la.size - COALESCE(pa.size, 0)) > 10 AND nos.num_order IS NOT NULL AND o.fraud THEN "CONFIRMED FRAUD ORDER"
WHEN (la.size - COALESCE(pa.size, 0)) > 10 AND nos.num_order IS NOT NULL AND NOT o.fraud THEN "POTENTIAL FRAUD ORDER"
ELSE ""
END AS notes
FROM latest_connect la
LEFT JOIN prev_connect pa ON la.account_id = pa.account_id
LEFT JOIN num_orders nos ON la.account_id = nos.account_id
LEFT JOIN orders o ON la.account_id = o.account_id
INNER JOIN edge_changes ec ON la.account_id = ec.account_id
WHERE nos.num_order > 1 OR (la.size - COALESCE(pa.size, 0)) > 10
ORDER BY diff DESC
הסבר על התוצאות
בדוח הזה מוצגים:
-
account_id: המזהה של החשבון שמנותח. order_id: מזהה הזמנה מהזמן האחרון.latest_size: הגודל של הרשת המחוברת היום.-
previous_size: הגודל של הרשת לפני שבועיים. -
diff: הצמיחה בגודל הרשת. -
num_order: מספר ההזמנות האחרונות. -
reported_as_fraud: האם ההזמנה סומנה כהונאה. -
order_total: הסכום הכולל של ההזמנה. notes: סטטוס סיכון מחושב שמבוסס על צמיחת הרשת והיסטוריית ההזמנות.
יוצגו לכם חשבונות עם ערכי diff גבוהים וסכומי הזמנות גבוהים, שהם מועמדים טובים לבדיקה נוספת. ההערות 'הלקוח בסיכון' ו'הזמנה עם פוטנציאל הונאה' עוזרות לתעדף את החשבונות האלה.

8. זיהוי בקנה מידה נרחב
בשלב הניתוח הסופי הזה, תהיה לכם אפשרות לראות את הרשת בקנה מידה גדול יותר. במקום להתחיל עם חשבון יחיד, תבצעו שאילתה לגבי קשרים בין קבוצה של חשבונות חשודים.
כך תוכלו לראות אם כמה חקירות עצמאיות הן למעשה חלק מרשת גדולה יותר של הונאה.
הרצת השאילתה המורחבת
מריצים את השאילתה הבאה במחברת.
%%bigquery --graph
GRAPH fraud_demo.FraudDemo
MATCH
p= ANY SHORTEST (a:Customer)
( -[e:OwnsEmail|OwnsPhone|LinkedToAddress]- (n) ){3, 5}
(reachable_a:Customer)
-- these IDs are from the previous results
WHERE a.account_id in ( "845f2b14-cd10-4750-9f28-fe542c4a731b"
, "3ff59684-fbf9-40d7-8c41-285ade5002e6"
, "8887c17b-e6fb-4b3b-8c62-cb721aafd028"
, "03e777e5-6fb4-445d-b48c-cf42b7620874"
, "81629832-eb1d-4a0e-86da-81a198604898"
, "845f2b14-cd10-4750-9f28-fe542c4a731b",
"89e9a8fe-ffc4-44eb-8693-a711a3534849"
)
LIMIT 400
RETURN TO_JSON(p) as paths
הסבר על התוצאות
השאילתה הזו מחזירה תרשים מורכב שמראה את החפיפה בין החשבונות החשודים שצוינו ואת המשאבים המשותפים שלהם. עכשיו אתם יכולים לראות את זיהוי ההונאות בהיקף נרחב, ולזהות קבוצות של פעילות שעשויות להצדיק תגובה מתואמת.

9. הסרת המשאבים
כדי להימנע מחיובים בחשבון Google Cloud על המשאבים שבהם השתמשתם ב-codelab הזה, מומלץ למחוק את מערך הנתונים ואת גרף הנכסים.
מריצים את הצהרות ה-SQL הבאות כדי לנקות את הסביבה.
DROP PROPERTY GRAPH IF EXISTS fraud_demo.FraudDemo;
DROP SCHEMA IF EXISTS fraud_demo CASCADE;
10. מזל טוב
מעולה! יצרתם בהצלחה פתרון לזיהוי הונאות באמצעות BigQuery Graph.
למדתם איך:
- טעינת נתונים מ-Cloud Storage ל-BigQuery.
- מגדירים גרף מאפיינים באמצעות DDL.
- שליחת שאילתות לגרף באמצעות GQL כדי למצוא קשרים פשוטים ומורכבים.
- שילוב של ניתוח גרפים עם נתונים עסקיים כדי לזהות סיכונים.
- הדמיה של רשתות בהיקף נרחב.
מקורות מידע נוספים