Deteksi Penipuan dengan BigQuery Graph

1. Pengantar

Header Pemasaran - Penipuan di Fintech

Aktivitas penipuan sering kali melibatkan jaringan tersembunyi dari entitas yang terhubung—misalnya, beberapa akun yang berbagi alamat email, nomor telepon, atau alamat fisik yang sama. Database relasional tradisional mungkin kesulitan mengkueri hubungan multi-hop yang kompleks ini secara efisien.

BigQuery Graph memungkinkan Anda menganalisis jaringan ini dalam skala besar menggunakan database grafik. Anda dapat menentukan grafik properti di atas tabel BigQuery yang ada dan menggunakan Graph Query Language (GQL) untuk menemukan pola dalam data Anda.

Aplikasi umum jaringan grafik untuk deteksi penipuan adalah menghentikan pesanan yang memiliki alamat pengiriman yang terkait dengan jaringan penipuan atau menghentikan pembayaran yang termasuk dalam .

Dalam codelab ini, Anda akan membangun solusi deteksi penipuan menggunakan BigQuery Graph. Anda akan memuat data dari Cloud Storage, membuat grafik properti, dan menggunakan kueri grafik untuk mengidentifikasi koneksi yang mencurigakan.

Yang akan Anda pelajari

  • Cara membuat set data BigQuery dan memuat data.
  • Cara menentukan grafik properti menggunakan DDL.
  • Cara membuat kueri grafik menggunakan GQL.
  • Cara menggunakan analisis grafik untuk mendeteksi penipuan.

Yang Anda butuhkan

  • Project Google Cloud yang mengaktifkan penagihan.
  • Lingkungan notebook BigQuery (BigQuery Studio atau Colab Enterprise).

Biaya

Lab ini menggunakan resource Google Cloud yang dapat ditagih. Perkiraan biaya kurang dari $5, dengan asumsi Anda menghapus resource setelah selesai.

2. Sebelum memulai

Memilih atau membuat project Google Cloud

  1. Di Konsol Google Cloud, pada halaman pemilih project, pilih atau buat project Google Cloud.
  2. Pastikan penagihan diaktifkan untuk project Google Cloud Anda. Pelajari cara memeriksa apakah penagihan telah diaktifkan.

Pilih lingkungan Anda

Anda memerlukan lingkungan notebook untuk menjalankan lab ini. Anda dapat menggunakan BigQuery Studio atau Colab Enterprise.

  1. Buka halaman BigQuery di Konsol Google Cloud.
  2. Anda akan menggunakan notebook python untuk menjalankan kueri grafik.

Mulai Cloud Shell

  1. Klik Activate Cloud Shell di bagian atas konsol Google Cloud.
  2. Verifikasi autentikasi:
gcloud auth list
  1. Konfirmasi project Anda:
gcloud config get project
  1. Tetapkan jika perlu:
export PROJECT_ID=<YOUR_PROJECT_ID>
gcloud config set project $PROJECT_ID

Mengaktifkan API

Jalankan perintah ini untuk mengaktifkan BigQuery API yang diperlukan:

gcloud services enable bigquery.googleapis.com

3. Muat Data

Pada langkah ini, Anda akan membuat set data BigQuery dan memuat data contoh dari Cloud Storage.

Contoh data terdiri dari beberapa file CSV yang merepresentasikan lingkungan retail simulasi:

  • customers.csv: Informasi akun pelanggan.
  • emails.csv: Alamat email.
  • phones.csv: Nomor telepon.
  • addresses.csv: Alamat fisik.
  • customer_emails.csv, customer_phones.csv, customer_addresses.csv: Menautkan tabel.
  • orders.csv: Histori pesanan, termasuk tanda penipuan.

Membuat Set Data

Buat set data bernama fraud_demo untuk menyimpan tabel.

  1. Untuk codelab ini, kita akan menjalankan perintah SQL. Anda dapat menjalankan perintah ini di BigQuery Studio > SQL Editor, atau menggunakan perintah bq query di Cloud Shell. Kueri SQL BaruKami akan menganggap Anda menggunakan BigQuery SQL Editor untuk mendapatkan pengalaman yang lebih baik dengan pernyataan pembuatan multi-baris.
CREATE SCHEMA IF NOT EXISTS `fraud_demo` OPTIONS(location="US");

Memuat Tabel

Jalankan pernyataan SQL berikut untuk memuat data dari Cloud Storage ke set data Anda.

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. Membuat Grafik Properti

Setelah data dimuat, Anda dapat menentukan grafik properti. Grafik properti terdiri dari node (entitas) dan edge (hubungan).

Dalam lab ini, node-nya adalah:

  • Pelanggan: Mewakili pemegang akun.
  • Telepon: Merepresentasikan nomor telepon.
  • Email: Mewakili alamat email.
  • Alamat: Merepresentasikan alamat fisik.

Tepi-tepinya adalah:

  • OwnsPhone: Menghubungkan Pelanggan ke Telepon.
  • OwnsEmail: Menghubungkan Pelanggan ke Email.
  • LinkedToAddress: Menghubungkan Pelanggan ke Alamat.

Buat Grafik

Jalankan pernyataan DDL berikut untuk membuat grafik bernama FraudDemo di set data fraud_demo Anda.

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. Menganalisis Jaringan (2 Hop)

Buka New Notebook di BigQuery Studio.

Buat Notebook Baru

Untuk bagian visualisasi dan rekomendasi dalam codelab ini, kita akan menggunakan notebook Google Colab di BigQuery Studio. Dengan begitu, kita dapat dengan mudah memvisualisasikan hasil grafik.

Notebook Grafik BigQuery diimplementasikan sebagai IPython Magics. Dengan menambahkan perintah ajaib %%bigquery dengan fungsi TO_JSON, Anda dapat memvisualisasikan hasilnya seperti yang ditunjukkan di bagian berikut. Pada langkah ini, Anda akan menjalankan kueri grafik untuk menemukan koneksi sederhana antar-akun. Ini adalah kueri "2-hop" karena melakukan 2 hop dari node awal untuk menemukan node terkait (misalnya, Pelanggan -> Email -> Pelanggan).

Kita akan mulai dengan menyelidiki akun milik Nicole Wade. Kita ingin menemukan akun apa pun yang terkait dengannya melalui 2 hop.

Menjalankan Kueri 2 Hop

Jalankan kueri berikut di notebook Anda.

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

Memahami Hasil

Kueri ini:

  1. Dimulai di node Customer dengan "d2f1f992-d116-41b3-955b-6c76a3352657" (Nicole Wade).account_id
  2. Mengikuti tepi OwnsEmail, OwnsPhone, atau LinkedToAddress ke node penghubung (Phone, Email, atau Address).
  3. Mengikuti tepi kembali dari node penghubung tersebut ke node Customer lainnya.
  4. Memfilter tepi berdasarkan stempel waktu (last_updated_ts) untuk melihat status jaringan pada waktu tertentu.

Anda akan melihat bahwa Zachary Cordova dan Brenda Brown terhubung ke Nicole melalui alamat yang sama.

6. Menganalisis Jaringan (4 Hop)

Pada langkah ini, Anda akan memperluas kueri untuk menemukan hubungan yang lebih kompleks. Kita akan mencari koneksi 4-hop. Hal ini memungkinkan kami menemukan akun yang terhubung melalui beberapa entitas perantara (misalnya, Pelanggan A -> Email -> Pelanggan B -> Telepon -> Pelanggan C).

Kami juga akan mengamati bagaimana perubahan jaringan ini dari waktu ke waktu.

Status "Sebelum"

Pertama, mari kita lihat jaringan seperti yang ada pada 30 Juli 2025.

Jalankan kueri berikut:

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

Status "Setelah"

Sekarang, mari kita lihat tampilan jaringan 2 minggu kemudian. Kita akan menjalankan kueri yang sama, tetapi tanpa batasan tanggal.

Jalankan kueri berikut:

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

Memahami Hasil

Dengan menghapus filter tanggal, Anda membuat kueri terhadap set data lengkap. Anda akan melihat bahwa jaringan telah berkembang secara signifikan. Nicole Wade kini menjadi bagian dari grup yang jauh lebih besar dan sangat terhubung. Perluasan jaringan terhubung yang cepat ini merupakan indikator kuat dari potensi aktivitas penipuan, seperti sindikat penipuan yang berbagi resource dari waktu ke waktu.

7. Buat Laporan Penipuan

Pada langkah ini, Anda akan menggabungkan analisis grafik dengan data bisnis tradisional (pesanan) untuk membuat laporan penipuan yang komprehensif. Anda akan mengidentifikasi akun yang berisiko dan potensi pesanan penipuan.

Kueri ini lebih kompleks. Langkah ini menggunakan GRAPH_TABLE untuk menjalankan kueri grafik dalam SQL standar dan menghitung perubahan ukuran jaringan (diff) antara status "sebelum" dan "sesudah" yang kita amati pada langkah sebelumnya.

Menjalankan Kueri Laporan Penipuan

Jalankan kueri berikut di notebook Anda.

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

Memahami Hasil

Laporan ini menampilkan:

  • account_id: ID akun yang sedang dianalisis.
  • order_id: ID pesanan terbaru.
  • latest_size: Ukuran jaringan yang terhubung saat ini.
  • previous_size: Ukuran jaringan 2 minggu lalu.
  • diff: Pertumbuhan ukuran jaringan.
  • num_order: Jumlah pesanan terbaru.
  • reported_as_fraud: Apakah pesanan telah ditandai sebagai penipuan.
  • order_total: Jumlah total pesanan.
  • notes: Status risiko yang dihitung berdasarkan pertumbuhan jaringan dan histori pesanan.

Anda akan melihat akun dengan nilai diff yang besar dan total pesanan yang tinggi, yang merupakan kandidat utama untuk penyelidikan lebih lanjut. Catatan "PELANGGAN BERISIKO" dan "PESANAN BERPOTENSI PENIPUAN" membantu memprioritaskan akun ini.

8. Deteksi dalam Skala Besar

Pada langkah analisis terakhir ini, Anda akan memvisualisasikan jaringan dalam skala yang lebih besar. Alih-alih memulai dengan satu akun, Anda akan membuat kueri untuk menemukan koneksi di antara sekumpulan akun yang mencurigakan.

Hal ini membantu Anda melihat apakah beberapa penyelidikan independen sebenarnya merupakan bagian dari sindikat penipuan yang lebih besar.

Menjalankan Kueri yang Diskalakan

Jalankan kueri berikut di notebook Anda.

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

Memahami Hasil

Kueri ini menampilkan grafik kompleks yang menunjukkan cara akun mencurigakan yang ditentukan tumpang-tindih dan berbagi resource. Sekarang Anda melihat deteksi penipuan dalam skala besar, mengidentifikasi kelompok aktivitas yang mungkin memerlukan respons terkoordinasi.

9. Pembersihan

Agar tidak menimbulkan biaya pada akun Google Cloud Anda untuk resource yang digunakan dalam codelab ini, Anda harus menghapus set data dan grafik properti.

Jalankan pernyataan SQL berikut untuk membersihkan lingkungan Anda.

DROP PROPERTY GRAPH IF EXISTS fraud_demo.FraudDemo;
DROP SCHEMA IF EXISTS fraud_demo CASCADE;

10. Selamat

Selamat! Anda telah berhasil membuat solusi deteksi penipuan menggunakan BigQuery Graph.

Anda telah mempelajari cara:

  • Memuat data dari Cloud Storage ke BigQuery.
  • Tentukan grafik properti menggunakan DDL.
  • Buat kueri pada grafik menggunakan GQL untuk menemukan hubungan sederhana dan kompleks.
  • Gabungkan analisis grafik dengan data bisnis untuk mengidentifikasi risiko.
  • Visualisasikan jaringan dalam skala besar.

Referensi Lainnya