1. Giới thiệu

Hoạt động gian lận thường liên quan đến các mạng lưới ẩn gồm các thực thể được kết nối – ví dụ: nhiều tài khoản dùng chung một địa chỉ email, số điện thoại hoặc địa chỉ thực tế. Các cơ sở dữ liệu quan hệ truyền thống có thể gặp khó khăn trong việc truy vấn hiệu quả các mối quan hệ phức tạp, nhiều bước nhảy này.
BigQuery Graph cho phép bạn phân tích các mạng lưới này trên quy mô lớn bằng cơ sở dữ liệu đồ thị. Bạn có thể xác định một đồ thị thuộc tính trên các bảng BigQuery hiện có và sử dụng Ngôn ngữ truy vấn đồ thị (GQL) để tìm các mẫu trong dữ liệu.
Một ứng dụng phổ biến của mạng lưới đồ thị để phát hiện gian lận là ngăn chặn các đơn đặt hàng có địa chỉ giao hàng liên kết với mạng lưới gian lận hoặc ngăn chặn các khoản thanh toán thuộc về .
Trong lớp học lập trình này, bạn sẽ xây dựng một giải pháp phát hiện gian lận bằng BigQuery Graph. Bạn sẽ tải dữ liệu từ Cloud Storage, tạo đồ thị thuộc tính và sử dụng các truy vấn đồ thị để xác định các kết nối đáng ngờ.
Kiến thức bạn sẽ học được
- Cách tạo tập dữ liệu BigQuery và tải dữ liệu.
- Cách xác định đồ thị thuộc tính bằng DDL.
- Cách truy vấn đồ thị bằng GQL.
- Cách sử dụng số liệu phân tích đồ thị để phát hiện gian lận.
Bạn cần có
- Một dự án trên Google Cloud đã bật tính năng thanh toán.
- Môi trường sổ ghi chú BigQuery (BigQuery Studio hoặc Colab Enterprise).
Chi phí
Lớp học lập trình này sử dụng các tài nguyên có tính phí của Google Cloud. Chi phí ước tính là dưới 5 USD, giả sử bạn xoá các tài nguyên sau khi hoàn tất.
2. Trước khi bắt đầu
Chọn hoặc tạo một dự án trên Google Cloud
- Trong Google Cloud Console, trên trang trình chọn dự án, hãy chọn hoặc tạo một dự án trên Google Cloud.
- Đảm bảo rằng bạn đã bật tính năng thanh toán cho dự án trên Google Cloud. Tìm hiểu cách kiểm tra xem tính năng thanh toán đã được bật hay chưa.
Chọn môi trường của bạn
Bạn cần có môi trường sổ ghi chú để chạy lớp học lập trình này. Bạn có thể sử dụng BigQuery Studio hoặc Colab Enterprise.
- Chuyển đến trang BigQuery trong Google Cloud Console.
- Bạn sẽ sử dụng sổ ghi chú Python để chạy các truy vấn đồ thị.
Bắt đầu Cloud Shell
- Nhấp vào Kích hoạt Cloud Shell ở đầu bảng điều khiển Cloud.
- Xác minh quy trình xác thực:
gcloud auth list
- Xác nhận dự án của bạn:
gcloud config get project
- Đặt dự án nếu cần:
export PROJECT_ID=<YOUR_PROJECT_ID>
gcloud config set project $PROJECT_ID
Bật API
Chạy lệnh này để bật BigQuery API bắt buộc:
gcloud services enable bigquery.googleapis.com
3. Tải dữ liệu
Trong bước này, bạn sẽ tạo một tập dữ liệu BigQuery và tải dữ liệu mẫu từ Cloud Storage.
Dữ liệu mẫu bao gồm một số tệp CSV đại diện cho môi trường bán lẻ mô phỏng:
customers.csv: Thông tin tài khoản khách hàng.emails.csv: Địa chỉ email.phones.csv: Số điện thoại.addresses.csv: Địa chỉ thực tế.customer_emails.csv,customer_phones.csv,customer_addresses.csv: Bảng liên kết.orders.csv: Nhật ký đơn hàng, bao gồm cả cờ gian lận.
Tạo tập dữ liệu
Tạo một tập dữ liệu có tên là fraud_demo để lưu giữ các bảng.
- Trong lớp học lập trình này, chúng ta sẽ thực thi các lệnh SQL. Bạn có thể chạy các lệnh này trong BigQuery Studio > SQL Editor hoặc sử dụng
bq querylệnh trong Cloud Shell.
Chúng tôi giả định rằng bạn đang sử dụng BigQuery SQL Editor để có trải nghiệm tốt hơn với các câu lệnh tạo nhiều dòng.
CREATE SCHEMA IF NOT EXISTS `fraud_demo` OPTIONS(location="US");
Tải bảng
Chạy các câu lệnh SQL sau để tải dữ liệu từ Cloud Storage vào tập dữ liệu.
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. Tạo đồ thị thuộc tính
Sau khi tải dữ liệu, bạn có thể xác định đồ thị thuộc tính. Đồ thị thuộc tính bao gồm các nút (thực thể) và cạnh (mối quan hệ).
Trong lớp học lập trình này, các nút là:
- Customer (Khách hàng): Đại diện cho chủ tài khoản.
- Phone (Điện thoại): Đại diện cho số điện thoại.
- Email (Email): Đại diện cho địa chỉ email.
- Address (Địa chỉ): Đại diện cho địa chỉ thực tế.
Các cạnh là:
- OwnsPhone (Sở hữu điện thoại): Kết nối Khách hàng với Điện thoại.
- OwnsEmail (Sở hữu email): Kết nối Khách hàng với Email.
- LinkedToAddress (Liên kết với địa chỉ): Kết nối Khách hàng với Địa chỉ.

Tạo đồ thị
Chạy câu lệnh DDL sau để tạo đồ thị có tên là FraudDemo trong tập dữ liệu 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. Phân tích mạng lưới (2 bước nhảy)
Mở New Notebook (Sổ ghi chú mới) trong BigQuery Studio.

Đối với các phần trực quan hoá và đề xuất của lớp học lập trình này, chúng ta sẽ sử dụng sổ ghi chú Google Colab trong BigQuery Studio. Điều này cho phép chúng ta dễ dàng trực quan hoá kết quả đồ thị.
Dán nội dung sau vào một ô mã:
!pip install bigquery-magics==0.12.1
Sổ ghi chú BigQuery Graph được triển khai dưới dạng IPython Magics. Bằng cách thêm lệnh magic %%bigquery với hàm TO_JSON, bạn có thể trực quan hoá kết quả như minh hoạ trong các phần sau. Trong bước này, bạn sẽ chạy một truy vấn đồ thị để tìm các kết nối đơn giản giữa các tài khoản. Đây là truy vấn "2 bước nhảy" vì truy vấn này di chuyển 2 bước nhảy từ một nút bắt đầu để tìm các nút liên quan (ví dụ: Khách hàng -> Email -> Khách hàng).
Chúng ta sẽ bắt đầu bằng cách điều tra tài khoản thuộc về Nicole Wade. Chúng ta muốn tìm bất kỳ tài khoản nào liên quan đến cô ấy thông qua 2 bước nhảy.
Chạy truy vấn 2 bước nhảy
Chạy truy vấn sau trong sổ ghi chú.
%%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

Tìm hiểu kết quả
Truy vấn này:
- Bắt đầu tại nút
Customercóaccount_id"d2f1f992-d116-41b3-955b-6c76a3352657" (Nicole Wade). - Theo dõi bất kỳ cạnh nào trong số các cạnh
OwnsEmail,OwnsPhone, hoặcLinkedToAddressđến một nút kết nối (Phone,Email, hoặcAddress). - Theo dõi các cạnh quay lại từ nút kết nối đó đến các nút
Customerkhác. - Lọc các cạnh dựa trên dấu thời gian (
last_updated_ts) để xem trạng thái của mạng lưới tại một thời điểm cụ thể.
Bạn sẽ thấy rằng Zachary Cordova và Brenda Brown được kết nối với Nicole thông qua cùng một địa chỉ.
6. Phân tích mạng lưới (4 bước nhảy)
Trong bước này, bạn sẽ mở rộng truy vấn để tìm các mối quan hệ phức tạp hơn. Chúng ta sẽ tìm kiếm các kết nối 4 bước nhảy. Điều này cho phép chúng ta tìm các tài khoản được kết nối thông qua một số thực thể trung gian (ví dụ: Khách hàng A -> Email -> Khách hàng B -> Điện thoại -> Khách hàng C).
Chúng ta cũng sẽ quan sát cách mạng lưới này thay đổi theo thời gian.
Trạng thái "Trước khi"
Trước tiên, hãy xem mạng lưới như tồn tại vào ngày 30 tháng 7 năm 2025.
Chạy truy vấn sau:
%%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

Trạng thái "Sau khi"
Bây giờ, hãy xem mạng lưới trông như thế nào 2 tuần sau. Chúng ta sẽ chạy cùng một truy vấn nhưng không có các hạn chế về ngày.
Chạy truy vấn sau:
%%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

Tìm hiểu kết quả
Bằng cách xoá các bộ lọc ngày, bạn đang truy vấn toàn bộ tập dữ liệu. Bạn sẽ nhận thấy rằng mạng lưới đã phát triển đáng kể. Nicole Wade hiện là một phần của một nhóm lớn hơn nhiều và có tính kết nối cao. Việc mạng lưới kết nối mở rộng nhanh chóng là một dấu hiệu mạnh mẽ cho thấy hoạt động gian lận tiềm ẩn, chẳng hạn như một nhóm gian lận chia sẻ tài nguyên theo thời gian.
7. Tạo báo cáo gian lận
Trong bước này, bạn sẽ kết hợp số liệu phân tích đồ thị với dữ liệu doanh nghiệp truyền thống (đơn đặt hàng) để tạo báo cáo gian lận toàn diện. Bạn sẽ xác định các tài khoản có nguy cơ và các đơn đặt hàng có khả năng gian lận.
Truy vấn này phức tạp hơn. Truy vấn này sử dụng GRAPH_TABLE để chạy truy vấn đồ thị bên trong SQL chuẩn và tính toán sự thay đổi về kích thước mạng lưới (diff) giữa trạng thái "trước khi" và "sau khi" mà chúng ta quan sát được ở bước trước.
Chạy truy vấn báo cáo gian lận
Chạy truy vấn sau trong sổ ghi chú.
%%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
Tìm hiểu kết quả
Báo cáo này cho thấy:
account_id: Mã của tài khoản đang được phân tích.order_id: Mã đơn đặt hàng gần đây.latest_size: Kích thước của mạng lưới kết nối ngày nay.previous_size: Kích thước của mạng lưới cách đây 2 tuần.diff: Mức tăng trưởng về kích thước mạng lưới.num_order: Số đơn đặt hàng gần đây.reported_as_fraud: Đơn đặt hàng đã được gắn cờ là gian lận hay chưa.order_total: Tổng số tiền của đơn đặt hàng.notes: Trạng thái rủi ro được tính toán dựa trên mức tăng trưởng mạng lưới và nhật ký đơn hàng.
Bạn sẽ thấy các tài khoản có giá trị diff lớn và tổng số đơn đặt hàng cao, đây là những ứng viên hàng đầu để điều tra thêm. Ghi chú "CUSTOMER AT RISK" (KHÁCH HÀNG CÓ NGUY CƠ) và "POTENTIAL FRAUD ORDER" (ĐƠN ĐẶT HÀNG CÓ KHẢ NĂNG GIAN LẬN) giúp ưu tiên các tài khoản này.

8. Phát hiện trên quy mô lớn
Trong bước phân tích cuối cùng này, bạn sẽ trực quan hoá mạng lưới trên quy mô lớn hơn. Thay vì bắt đầu bằng một tài khoản duy nhất, bạn sẽ truy vấn các kết nối giữa một tập hợp các tài khoản đáng ngờ.
Điều này giúp bạn biết liệu nhiều cuộc điều tra độc lập có thực sự là một phần của cùng một nhóm gian lận lớn hơn hay không.
Chạy truy vấn được điều chỉnh theo quy mô
Chạy truy vấn sau trong sổ ghi chú.
%%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
Tìm hiểu kết quả
Truy vấn này trả về một đồ thị phức tạp cho thấy cách các tài khoản đáng ngờ được chỉ định chồng chéo và chia sẻ tài nguyên. Bây giờ, bạn đang xem xét việc phát hiện gian lận trên quy mô lớn, xác định các cụm hoạt động có thể cần phản hồi phối hợp.

9. Dọn dẹp
Để tránh bị tính phí vào tài khoản Google Cloud cho các tài nguyên được sử dụng trong lớp học lập trình này, bạn nên xoá tập dữ liệu và đồ thị thuộc tính.
Chạy các câu lệnh SQL sau để dọn dẹp môi trường.
DROP PROPERTY GRAPH IF EXISTS fraud_demo.FraudDemo;
DROP SCHEMA IF EXISTS fraud_demo CASCADE;
10. Xin chúc mừng
Xin chúc mừng! Bạn đã xây dựng thành công một giải pháp phát hiện gian lận bằng BigQuery Graph.
Bạn đã học được cách:
- Tải dữ liệu từ Cloud Storage vào BigQuery.
- Xác định đồ thị thuộc tính bằng DDL.
- Truy vấn đồ thị bằng GQL để tìm các mối quan hệ đơn giản và phức tạp.
- Kết hợp số liệu phân tích đồ thị với dữ liệu doanh nghiệp để xác định rủi ro.
- Trực quan hoá mạng lưới trên quy mô lớn.