Phát hiện hành vi gian lận bằng BigQuery Graph

1. Giới thiệu

Tiêu đề tiếp thị – Gian lận trong lĩnh vực công nghệ tài chính

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

  1. 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.
  2. Đả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.

  1. Chuyển đến trang BigQuery trong Google Cloud Console.
  2. Bạn sẽ dùng sổ tay python để chạy các truy vấn đồ thị.

Khởi động Cloud Shell

  1. Nhấp vào Kích hoạt Cloud Shell ở đầu bảng điều khiển Cloud.
  2. Xác minh hoạt động xác thực:
gcloud auth list
  1. Xác nhận dự án của bạn:
gcloud config get project
  1. Đặ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.

  1. 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 query trong Cloud Shell. Truy vấn SQL mớiChú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.

Tạo sổ tay mới

Đố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:

  1. Bắt đầu tại nút Customer với account_id "d2f1f992-d116-41b3-955b-6c76a3352657" (Nicole Wade).
  2. Theo bất kỳ cạnh nào trong số OwnsEmail, OwnsPhone hoặc LinkedToAddress đến một nút kết nối (Phone, Email hoặc Address).
  3. Theo các cạnh ngược lại từ nút kết nối đó đến các nút Customer khác.
  4. 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 CordovaBrenda 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