1. Giới thiệu

Hoạt động gian lận thường liên quan đến các mạng lưới ẩn của các thực thể có liên kết với nhau, chẳng hạn như 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ả những mối quan hệ phức tạp, nhiều bước này.
BigQuery Graph cho phép bạn phân tích các mạng này ở quy mô lớn bằng cách sử dụng cơ sở dữ liệu đồ thị. Bạn có thể xác định biểu đồ tài sản dựa trên các bảng BigQuery hiện có và sử dụng Ngôn ngữ truy vấn biểu đồ (GQL) để tìm các mẫu trong dữ liệu của mình.
Một ứng dụng phổ biến của mạng đồ thị để phát hiện hành vi gian lận là ngăn chặn những đơ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 những 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 hành vi gian lận bằng BigQuery Graph. Bạn sẽ tải dữ liệu từ Cloud Storage, tạo một biểu đồ thuộc tính và sử dụng các truy vấn biểu đồ để xác định các mối 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 biểu đồ thuộc tính bằng DDL.
- Cách truy vấn biểu đồ bằng GQL.
- Cách sử dụng số liệu phân tích biểu đồ để phát hiện hành vi 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ổ tay BigQuery (BigQuery Studio hoặc Colab Enterprise).
Chi phí
Bài tập thực hà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 chọn dự án, hãy chọn hoặc tạo một dự án Google Cloud.
- Đảm bảo 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 bạn đã bật tính năng thanh toán hay chưa.
Chọn môi trường của bạn
Bạn cần có một môi trường sổ tay để chạy phòng thí nghiệm 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ẽ dùng sổ tay python để chạy các truy vấn đồ thị.
Khởi động Cloud Shell
- Nhấp vào Kích hoạt Cloud Shell ở đầu bảng điều khiển Cloud.
- Xác minh hoạt động xác thực:
gcloud auth list
- Xác nhận dự án của bạn:
gcloud config get project
- Đặt 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
Ở 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ột 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: Liên kết các bảng.orders.csv: Nhật ký đặt 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 > Trình chỉnh sửa SQL hoặc sử dụng lệnh
bq querytrong Cloud Shell.
Chúng tôi giả định rằng bạn đang sử dụng Trình chỉnh sửa SQL của BigQuery để 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 của bạn.
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 biểu đồ thuộc tính
Giờ đây, khi dữ liệu đã được tải, bạn có thể xác định biểu đồ thuộc tính. Biểu đồ thuộc tính bao gồm các nút (thực thể) và cạnh (mối quan hệ).
Trong phòng thí nghiệm này, các nút là:
- Khách hàng: Đại diện cho chủ tài khoản.
- Điện thoại: Biểu thị một số điện thoại.
- Email: Đại diện cho một địa chỉ email.
- Địa chỉ: Biểu thị một địa chỉ thực tế.
Các cạnh là:
- OwnsPhone: Kết nối Khách hàng với Điện thoại.
- OwnsEmail: Kết nối Khách hàng với Email.
- LinkedToAddress: Kết nối Khách hàng với Địa chỉ.

Tạo biểu đồ
Chạy câu lệnh DDL sau đây để tạo biểu đồ 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 (2 bước nhảy)
Mở Sổ tay 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 một sổ tay Google Colab trong BigQuery Studio. Nhờ đó, chúng ta có thể dễ dàng hình dung kết quả của biểu đồ.
BigQuery Graph Notebook được triển khai dưới dạng IPython Magics. Bằng cách thêm lệnh %%bigquery (lệnh đặc biệt) bằng 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 mối kết nối đơn giản giữa các tài khoản. Đây là một truy vấn "2 bước" vì truy vấn này di chuyển 2 bước từ một nút bắt đầu để tìm các nút có liên quan (ví dụ: Khách hàng -> Email -> Khách hàng).
Chúng tôi sẽ bắt đầu bằng việc điều tra tài khoản của Nicole Wade. Chúng tôi muốn tìm mọi tài khoản liên quan đến cô ấy qua 2 bước.
Chạy truy vấn 2 bước
Chạy truy vấn sau trong sổ tay của bạn.
%%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
Customervớiaccount_id"d2f1f992-d116-41b3-955b-6c76a3352657" (Nicole Wade). - Theo bất kỳ cạnh nào trong số
OwnsEmail,OwnsPhonehoặcLinkedToAddressđến một nút kết nối (Phone,EmailhoặcAddress). - Theo các cạnh ngược 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 tại một thời điểm cụ thể.
Bạn sẽ thấy 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 (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 tôi tìm thấy những 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 tôi cũng sẽ theo dõi những thay đổi của mạng lưới này theo thời gian.
Trạng thái "Trước"
Trước tiên, hãy xem mạng lưới này vào ngày 30 tháng 7 năm 2025.
Chạy truy vấn sau:
%%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

Trạng thái "Sau"
Bây giờ, hãy xem mạng lưới này trông như thế nào 2 tuần sau. Chúng tôi 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ả
Khi xoá bộ lọc ngày, bạn đang truy vấn dựa trên toàn bộ tập dữ liệu. Bạn sẽ nhận thấy rằng mạng lưới này đã phát triển đáng kể. Nicole Wade hiện là thành viên của một nhóm lớn hơn nhiều và có mối liên kết chặt chẽ. 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 phân tích đồ thị với dữ liệu doanh nghiệp truyền thống (số đơn đặt hàng) để tạo một báo cáo toàn diện về hành vi gian lận. Bạn sẽ xác định được những tài khoản có rủi ro và đơn đặt hàng có thể gian lận.
Cụm từ tìm kiếm này phức tạp hơn. Thao tác này sử dụng GRAPH_TABLE để chạy truy vấn biểu đồ trong SQL chuẩn và tính toán mức thay đổi về kích thước mạng (diff) giữa trạng thái "trước" và "sau" 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ổ tay của bạn.
%%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 biết:
account_id: Mã nhận dạng của tài khoản đang được phân tích.order_id: Mã đơn đặt hàng gần đây.latest_size: Quy mô của mạng lưới được kết nối hiện tại.previous_size: Quy mô của mạng lưới cách đây 2 tuần.diff: Sự tăng trưởng về quy mô mạng.num_order: Số đơn đặt hàng gần đây.reported_as_fraud: Đơn đặt hàng đã bị 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 và nhật ký đơn hàng.
Bạn sẽ thấy những tài khoản có giá trị diff lớn và tổng số đơn đặt hàng cao. Đây là những tài khoản cần được điều tra thêm. Các ghi chú "KHÁCH HÀNG CÓ RỦI RO" và "ĐƠN ĐẶT HÀNG CÓ THỂ LÀ GIAN LẬN" giúp bạn ưu tiên những 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ẽ hình dung mạng ở 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 mối kết nối giữa một nhóm 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 mạng lưới lừa đảo lớn hơn hay không.
Chạy truy vấn được mở rộng
Chạy truy vấn sau trong sổ tay của bạn.
%%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 biểu đồ phức tạp cho biết mức độ trùng lặp và chia sẻ tài nguyên của các tài khoản đáng ngờ được chỉ định. Giờ đây, bạn đang xem xét việc phát hiện hành vi gian lận trên quy mô lớn, xác định các cụm hoạt động có thể cần đến một biện pháp ứng phó phối hợp.

9. Dọn dẹp
Để tránh phát sinh phí cho tài khoản Google Cloud của bạn đối với các tài nguyên được dùng trong lớp học lập trình này, bạn nên xoá tập dữ liệu và biểu đồ tài sản.
Chạy các câu lệnh SQL sau để dọn dẹp môi trường của bạn.
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 hành vi gian lận bằng BigQuery Graph.
Bạn đã tìm hiểu cách:
- Tải dữ liệu từ Cloud Storage vào BigQuery.
- Xác định biểu đồ 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 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 ở quy mô lớn.
Các tài nguyên khác