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 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

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

  1. Chuyển đến trang BigQuery trong Google Cloud Console.
  2. Bạn sẽ sử dụng sổ ghi chú Python để chạy các truy vấn đồ thị.

Bắt đầu 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 quy trình xác thực:
gcloud auth list
  1. Xác nhận dự án của bạn:
gcloud config get project
  1. Đặ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.

  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 > SQL Editor hoặc sử dụng bq query lệnh trong Cloud Shell. Truy vấn SQL mớiChú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.

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

  1. Bắt đầu tại nút Customeraccount_id "d2f1f992-d116-41b3-955b-6c76a3352657" (Nicole Wade).
  2. Theo dõi bất kỳ cạnh nào trong số các cạnh OwnsEmail, OwnsPhone, hoặc LinkedToAddress đến một nút kết nối (Phone, Email, hoặc Address).
  3. Theo dõi các cạnh quay 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 lưới tại một thời điểm cụ thể.

Bạn sẽ thấy rằng 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 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.

Các tài nguyên khác