1. Wprowadzenie

Nieuczciwe działanie często obejmuje ukryte sieci powiązanych ze sobą encji, np. wiele kont korzystających z tego samego adresu e-mail, numeru telefonu lub adresu pocztowego. Tradycyjne relacyjne bazy danych mogą mieć problemy z efektywnym wykonywaniem zapytań dotyczących tych złożonych relacji wielokrotnych.
BigQuery Graph umożliwia analizowanie tych sieci na dużą skalę za pomocą grafowych baz danych. Możesz zdefiniować graf właściwości na podstawie istniejących tabel BigQuery i użyć języka zapytań grafowych (GQL), aby znaleźć wzorce w swoich danych.
Typowym zastosowaniem sieci grafowych do wykrywania oszustw jest blokowanie zamówień z adresem dostawy powiązanym z siecią oszustw lub blokowanie płatności należących do .
W tym ćwiczeniu utworzysz rozwiązanie do wykrywania oszustw za pomocą BigQuery Graph. Wczytasz dane z Cloud Storage, utworzysz graf właściwości i użyjesz zapytań grafowych do identyfikowania podejrzanych połączeń.
Czego się nauczysz
- Jak utworzyć zbiór danych BigQuery i wczytać dane.
- Jak zdefiniować graf właściwości za pomocą DDL.
- Jak wykonywać zapytania na grafie za pomocą GQL.
- Jak używać analizy grafów do wykrywania oszustw.
Czego potrzebujesz
- Projekt Google Cloud z włączonymi płatnościami.
- Środowisko notatnika BigQuery (BigQuery Studio lub Colab Enterprise).
Koszt
To laboratorium korzysta z płatnych zasobów Google Cloud. Szacowany koszt to mniej niż 5 USD, jeśli po zakończeniu ćwiczenia usuniesz zasoby.
2. Zanim zaczniesz
Wybierz lub utwórz projekt Google Cloud
- W konsoli Google Cloud na stronie wyboru projektu wybierz lub utwórz projekt w chmurze Google Cloud.
- Sprawdź, czy w projekcie Google Cloud włączone są płatności. Dowiedz się, jak sprawdzić, czy płatności są włączone.
Wybierz środowisko
Aby wykonać to ćwiczenie, potrzebujesz środowiska notatnika. Możesz użyć BigQuery Studio lub Colab Enterprise.
- W konsoli Google Cloud otwórz stronę BigQuery.
- Do uruchamiania zapytań grafowych będziesz używać notatnika Pythona.
Uruchamianie Cloud Shell
- Kliknij Aktywuj Cloud Shell u góry konsoli Google Cloud.
- Sprawdź uwierzytelnianie:
gcloud auth list
- Potwierdź swój projekt:
gcloud config get project
- W razie potrzeby ustaw go:
export PROJECT_ID=<YOUR_PROJECT_ID>
gcloud config set project $PROJECT_ID
Włącz interfejsy API
Aby włączyć wymagany interfejs API BigQuery, uruchom to polecenie:
gcloud services enable bigquery.googleapis.com \
bigqueryreservation.googleapis.com
Tworzenie rezerwacji i przypisania BigQuery
Aby uruchamiać zapytania GQL, musisz mieć rezerwację, która korzysta z wersji Enterprise lub Enterprise Plus. Utwórz rezerwację w wersji Enterprise z autoskalowaniem w Cloud Shell:
# 1. Create a BigQuery Enterprise reservation with 0 baseline slots and 100 max autoscaling slots
bq mk --reservation \
--project_id=${GCP_PROJECT} \
--location=US \
--edition=ENTERPRISE \
--slots=0 \
--autoscale_max_slots=100 \
--ignore_idle_slots=true \
fraud-reservation
# 2. Assign your Cloud project to the newly created reservation for query execution
bq mk --reservation_assignment \
--project_id=${GCP_PROJECT} \
--location=US \
--reservation_id=fraud-reservation \
--job_type=QUERY \
--assignee_type=PROJECT \
--assignee_id=${GCP_PROJECT}
3. Wczytaj dane
W tym kroku utworzysz zbiór danych BigQuery i wczytasz przykładowe dane z Cloud Storage.
Przykładowe dane składają się z kilku plików CSV reprezentujących symulowane środowisko handlu detalicznego:
customers.csv: informacje o koncie klienta.emails.csv: adresy e-mail.phones.csv: numery telefonów.addresses.csv: adresy fizyczne.customer_emails.csv,customer_phones.csv,customer_addresses.csv: tabele łączące.orders.csv: historia zamówień, w tym flagi oszustw.
Utwórz zbiór danych
Utwórz zbiór danych o nazwie fraud_demo, w którym będą przechowywane tabele.
- W tym ćwiczeniu będziemy wykonywać polecenia SQL. Możesz uruchamiać te polecenia w BigQuery Studio > Edytor SQL lub użyć polecenia
bq queryw Cloud Shell.
Zakładamy, że używasz edytora SQL BigQuery, aby zapewnić lepsze wrażenia podczas tworzenia instrukcji wielowierszowych.
CREATE SCHEMA IF NOT EXISTS `fraud_demo` OPTIONS(location="US");
Wczytaj tabele
Aby wczytać dane z Cloud Storage do zbioru danych, uruchom te instrukcje SQL.
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. Utwórz graf właściwości
Gdy dane zostaną wczytane, możesz zdefiniować graf właściwości. Graf właściwości składa się z węzłów (encji) i krawędzi (relacji).
W tym laboratorium węzły to:
- Klient: reprezentuje właściciela konta.
- Telefon: reprezentuje numer telefonu.
- E-mail: reprezentuje adres e-mail.
- Adres: reprezentuje adres fizyczny.
Krawędzie to:
- OwnsPhone: łączy klienta z telefonem.
- OwnsEmail: łączy klienta z adresem e-mail.
- LinkedToAddress: łączy klienta z adresem.

Utwórz graf
Aby utworzyć graf o nazwie FraudDemo w zbiorze danych fraud_demo, uruchom tę instrukcję DDL.
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. Analizowanie sieci (2 przeskoki)
W BigQuery Studio otwórz Nowy notatnik.

W częściach tego ćwiczenia dotyczących wizualizacji i rekomendacji będziemy używać notatnika Google Colab w BigQuery Studio. Umożliwi nam to łatwe wizualizowanie wyników grafu.
Wklej to do komórki kodu:
!pip install bigquery-magics==0.12.1
Notatnik BigQuery Graph jest zaimplementowany jako IPython Magics. Dodając polecenie magiczne %%bigquery z funkcją TO_JSON, możesz wizualizować wyniki w sposób opisany w kolejnych sekcjach. W tym kroku uruchomisz zapytanie grafowe, aby znaleźć proste połączenia między kontami. Jest to zapytanie „2 przeskoki”, ponieważ przeskakuje 2 przeskoki od węzła początkowego, aby znaleźć powiązane węzły (np. Klient -> E-mail -> Klient).
Zacznijmy od zbadania konta należącego do Nicole Wade. Chcemy znaleźć wszystkie konta powiązane z nią za pomocą 2 przeskoki.
Uruchom zapytanie 2 przeskoki
Uruchom to zapytanie w notatniku.
%%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

Interpretowanie wyników
To zapytanie:
- Zaczyna się od węzła
Customerzaccount_id„d2f1f992-d116-41b3-955b-6c76a3352657” (Nicole Wade). - Podąża za dowolną krawędzią
OwnsEmail,OwnsPhone, lubLinkedToAddressdo węzła łączącego (Phone,Email, lubAddress). - Podąża za krawędziami z powrotem z tego węzła łączącego do innych węzłów
Customer. - Filtruje krawędzie na podstawie sygnatury czasowej (
last_updated_ts), aby zobaczyć stan sieci w określonym czasie.
Powinno się wyświetlić, że Zachary Cordova i Brenda Brown są powiązane z Nicole za pomocą tego samego adresu.
6. Analizowanie sieci (4 przeskoki)
W tym kroku rozszerzysz zapytanie, aby znaleźć bardziej złożone relacje. Będziemy szukać połączeń 4 przeskoki. Umożliwi nam to znajdowanie kont, które są połączone za pomocą kilku podmiotów pośrednich (np. Klient A -> E-mail -> Klient B -> Telefon -> Klient C).
Zaobserwujemy też, jak ta sieć zmienia się w czasie.
Stan „przed”
Najpierw przyjrzyjmy się sieci w stanie z 30 lipca 2025 r.
Uruchom to zapytanie:
%%bigquery --graph
GRAPH fraud_demo.FraudDemo
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)]))
RETURN
TO_JSON(p) AS paths, -- Array of all traversed edges
ARRAY_LENGTH(e) AS hop_count

Stan „po”
Teraz zobaczmy, jak wygląda sieć 2 tygodnie później. Uruchomimy to samo zapytanie, ale bez ograniczeń daty.
Uruchom to zapytanie:
%%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

Interpretowanie wyników
Usuwając filtry daty, wykonujesz zapytanie na całym zbiorze danych. Zauważysz, że sieć znacznie się rozrosła. Nicole Wade jest teraz częścią znacznie większej, silnie połączonej grupy. Szybkie rozszerzanie się połączonej sieci jest silnym wskaźnikiem potencjalnych działań oszukańczych, takich jak grupa oszustów udostępniająca zasoby w czasie.
7. Generowanie raportu o oszustwach
W tym kroku połączysz analizę grafów z tradycyjnymi danymi biznesowymi (zamówieniami), aby wygenerować kompleksowy raport o oszustwach. Zidentyfikujesz konta zagrożone i potencjalne zamówienia oszukańcze.
To zapytanie jest bardziej złożone. Używa GRAPH_TABLE do uruchamiania zapytania grafowego w standardowej wersji SQL i oblicza zmianę rozmiaru sieci (diff) między stanem „przed” a „po”, który zaobserwowaliśmy w poprzednim kroku.
Uruchom zapytanie raportu o oszustwach
Uruchom to zapytanie w notatniku.
%%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
Interpretowanie wyników
Ten raport pokazuje:
account_id: identyfikator analizowanego konta.order_id: identyfikator ostatniego zamówienia.latest_size: rozmiar połączonej sieci.previous_size: rozmiar sieci 2 tygodnie temu.diff: wzrost rozmiaru sieci.num_order: liczba ostatnich zamówień.reported_as_fraud: czy zamówienie zostało oznaczone jako oszukańcze.order_total: łączna kwota zamówienia.notes: obliczony stan ryzyka na podstawie wzrostu sieci i historii zamówień.
Zobaczysz konta z dużymi wartościami diff i wysokimi łącznymi kwotami zamówień, które są głównymi kandydatami do dalszego zbadania. Notatki „KLIENT ZAGROŻONY” i „POTENCJALNE ZAMÓWIENIE OSZUKAŃCZE” pomagają ustalić priorytety tych kont.

8. Wykrywanie na dużą skalę
W tym ostatnim kroku analizy wizualizujesz sieć na większą skalę. Zamiast zaczynać od jednego konta, będziesz wykonywać zapytania o połączenia między zestawem podejrzanych kont.
Pomoże Ci to sprawdzić, czy kilka niezależnych dochodzeń jest w rzeczywistości częścią tej samej większej grupy oszustów.
Uruchom zapytanie na dużą skalę
Uruchom to zapytanie w notatniku.
%%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
Interpretowanie wyników
To zapytanie zwraca złożony graf pokazujący, jak określone podejrzane konta nakładają się na siebie i udostępniają zasoby. Teraz możesz wykrywać oszustwa na dużą skalę, identyfikując klastry aktywności, które mogą wymagać skoordynowanej reakcji.

9. Czyszczenie
Aby uniknąć obciążenia konta Google Cloud opłatami za zasoby użyte w tym ćwiczeniu, usuń zbiór danych i graf właściwości.
Uruchom następujące instrukcje SQL, aby zwolnić miejsce w środowisku.
DROP PROPERTY GRAPH IF EXISTS fraud_demo.FraudDemo;
DROP SCHEMA IF EXISTS fraud_demo CASCADE;
10. Gratulacje
Gratulacje! Udało Ci się utworzyć rozwiązanie do wykrywania oszustw za pomocą BigQuery Graph.
Dowiedziałeś się, jak:
- wczytywać dane z Cloud Storage do BigQuery;
- definiować graf właściwości za pomocą DDL;
- wykonywać zapytania na grafie za pomocą GQL, aby znaleźć proste i złożone relacje;
- łączyć analizę grafów z danymi biznesowymi, aby identyfikować ryzyko;
- wizualizować sieci na dużą skalę.