Cloud Spanner: ข้อมูลเชิงลึกของกราฟโดยใช้อัลกอริทึม Spanner Graph

1. กรณีศึกษา: การค้าปลีกอัจฉริยะ

สำหรับกรณีศึกษา เราจะใช้ลูกค้ารายย่อยที่มีตลาดดิจิทัลที่เติบโตอย่างรวดเร็ว มุมมองข้อมูลแบบเดิมของลูกค้ามีข้อจำกัดเนื่องจากแสดงสิ่งที่ผู้คนซื้อ แต่ไม่ได้แสดงวิธีที่ผู้คนเชื่อมต่อกัน ช่องว่างนี้ทำให้พลาดโอกาสและเกิดการฉ้อโกงมากขึ้น ปัจจุบันบริษัทกำลังเปลี่ยนไปใช้ปรัชญาเครือข่ายเป็นอันดับแรกเพื่อประเมินการเชื่อมต่อทางสังคมและการเชื่อมต่อด้านลอจิสติกส์นอกเหนือจากข้อมูลธุรกรรม

ความท้าทายหลักทางธุรกิจที่ต้องแก้ไข

คุณมีปัญหาสำคัญ 4 ประการที่ต้องทำความเข้าใจวิธีที่ลูกค้าและโลจิสติกส์เชื่อมโยงกัน

ภารกิจ

ปัญหา

เป้าหมาย

ช่องว่างของอิทธิพล

การโฆษณาแบบกว้างให้ ROI ต่ำ ปัจจุบันยังไม่สามารถระบุผู้กำหนดเทรนด์ (อินฟลูเอนเซอร์) ที่แท้จริงได้

ระบุอินฟลูเอนเซอร์ที่เป็นศูนย์กลางของชุมชนผ่านการเชื่อมต่อในเครือข่ายลูกค้าที่เชื่อมต่อกัน

ความพร้อมรับมือกับปัญหาด้านโลจิสติกส์

ซัพพลายเชนอาจมีความเสี่ยง (เนื่องจากมีการดำเนินงานในพื้นที่ทางภูมิศาสตร์ที่แตกต่างกัน) หากฮับคีย์ใดคีย์หนึ่งล้มเหลว ภูมิภาคทั้งหมดอาจเสียสิทธิ์เข้าถึงผลิตภัณฑ์

ระบุผู้ดูแล ซึ่งเป็นบุคคลสำคัญในการเชื่อมต่อเครือข่ายโลจิสติกส์เข้าด้วยกัน

เครือข่ายผี

แก๊งฉ้อโกงใช้โปรไฟล์ปลอมและที่อยู่ที่ใช้ร่วมกันเพื่อประสานงานการขโมยและเพิ่มคะแนน

เปิดเผยเกาะที่แยกตัว กลุ่มที่เชื่อมต่อกันอย่างแน่นแฟ้นโดยไม่มีความเกี่ยวข้องกับชุมชนที่ถูกต้อง

Paradox of Choice

เครื่องมือแนะนำ/แนะนำในปัจจุบันยังไม่ซับซ้อน เป็นแบบทั่วไป และมักถูกมองข้าม (เช่น "ลูกค้าที่ซื้อรายการนี้ยังซื้อ ...")

สร้างกลุ่มเป้าหมายที่คล้ายกันตามพฤติกรรม ซึ่งก็คือคำแนะนำที่อิงตามรูปแบบการจัดส่งและวงสังคมที่คล้ายกัน

การเชื่อมโยงความท้าทายทางธุรกิจกับกลยุทธ์ทางเทคนิค (แถว → ความสัมพันธ์)

ในฐานข้อมูลแบบดั้งเดิม ข้อมูลจะจัดเก็บไว้ในไซโลที่แยกกัน โดยลูกค้าจะอยู่ในตารางหนึ่ง ธุรกรรมจะอยู่ในอีกตารางหนึ่ง และการจัดส่งจะอยู่ในตารางที่สาม แม้ว่า SQL จะเหมาะอย่างยิ่งสำหรับการตอบคำถามที่ว่า "ใครซื้ออะไร" แต่ก็ตอบคำถามที่อิงตามเครือข่ายได้ยาก

กลยุทธ์ทางเทคนิคในการแก้ปัญหาเหล่านี้คือการเปลี่ยนมุมมองดังนี้

  • มุมมองเชิงสัมพันธ์ ("อะไร"): ถือว่าลูกค้าทุกคนเป็นแถวที่แยกกัน การค้นหาความเชื่อมโยงระหว่างลูกค้ากับการซื้อของเพื่อนต้องใช้การ "รวม" ที่ซับซ้อนหลายรายการ ซึ่งจะช้าลงอย่างมากเมื่อเครือข่ายเติบโตขึ้น
  • มุมมองกราฟ ("วิธี"): ถือว่าความสัมพันธ์เป็นสิ่งสำคัญอันดับแรก เราจะนำทางในแผนที่แทนที่จะค้นหาในรายการ เราจะเห็นทันทีว่าลูกค้า ก เชื่อมต่อกับลูกค้า ข ซึ่งจัดส่งไปยังสถานที่ตั้ง ง

เจาะลึกข้อกำหนด

สถาปนิกโซลูชันสรุปว่าข้อกำหนดทางธุรกิจและกลยุทธ์ทางเทคนิคต้องใช้แนวทางแบบหลายโมเดล และระบุข้อกำหนดสำคัญต่อไปนี้

Cloud Spanner ตอบโจทย์ข้อกำหนดทางเทคนิคเหล่านั้นได้อย่างไร

เราเลือก Cloud Spanner เป็นหัวใจสำคัญของการเปลี่ยนแปลงนี้ ซึ่งช่วยให้ลูกค้าสามารถรักษาพื้นฐานความสัมพันธ์ที่มั่นคงไว้ได้พร้อมๆ กับการปลดล็อกข้อมูลเชิงลึกของกราฟ

ต่อไปนี้เป็นข้อมูลคร่าวๆ เกี่ยวกับวิธีที่ Cloud Spanner ตอบสนองข้อกำหนดทางเทคนิคและอื่นๆ

นอกจากนี้ Cloud Spanner ยังมีสถาปัตยกรรมทางเทคนิคที่พร้อมรับมือกับอนาคต

2. การสร้างรากฐานข้อมูล

หลังจากพิจารณากรณีการใช้งานทางธุรกิจแล้ว ตอนนี้เราจะเข้าสู่ระยะการติดตั้งใช้งาน ในส่วนนี้ เราจะกำหนดสถาปัตยกรรมข้อมูล สำรวจข้อจำกัดของโมเดลเชิงสัมพันธ์แบบดั้งเดิม และแนะนำกราฟพร็อพเพอร์ตี้เป็นเครื่องมือหลักในการค้นพบข้อมูลเชิงลึก

ตั้งค่าอินสแตนซ์ Cloud Spanner Enterprise

ขั้นตอนที่ 1: เปิดใช้ Cloud Spanner API

ใน คอนโซล Google Cloud ให้คลิกไอคอนเมนูที่ด้านซ้ายบนของหน้าจอเพื่อดูการนำทางด้านซ้าย เลื่อนลงแล้วเลือก "Spanner" หรือค้นหา "Spanner"

ตอนนี้คุณควรเห็น UI ของ Cloud Spanner และหากใช้โปรเจ็กต์ที่ยังไม่ได้เปิดใช้ Cloud Spanner API คุณจะเห็นกล่องโต้ตอบที่ขอให้คุณเปิดใช้ หากเปิดใช้ API แล้ว ให้ข้ามขั้นตอนนี้

คลิก "เปิดใช้" เพื่อดำเนินการต่อ

1d9ce329b076805a.png

ขั้นตอนที่ 2: สร้างอินสแตนซ์ Cloud Spanner

ก่อนอื่น คุณจะต้องสร้างอินสแตนซ์ Cloud Spanner ใน UI ให้คลิก "สร้างอินสแตนซ์ที่จัดสรร" เพื่อสร้างอินสแตนซ์ใหม่

ในขั้นตอนแรก คุณต้องเลือกฉบับ โปรดทราบว่าคุณสามารถอัปเกรดรุ่นได้ในภายหลังด้วย หากต้องการใช้ความสามารถแบบหลายโมเดล (Spanner Graph) เราสามารถใช้รุ่น Enterprise ได้

c44a0b5b5ba24877.png

การตั้งชื่ออินสแตนซ์

9cf487f702beece3.png

เลือกการกำหนดค่าการติดตั้งใช้งานและเลือกภูมิภาคที่ต้องการ

f2c4c364703aecf.png

นอกจากนี้ คุณยังเปรียบเทียบตัวเลือกการกำหนดค่าต่างๆ ได้ด้วย เช่น การกำหนดค่าการทำให้ใช้งานได้มีตัวจำลอง R/W อย่างน้อย 3 รายการใน 3 โซนแยกกันของภูมิภาคที่คุณเลือก กล่าวคือ แม้ว่าคุณจะเลือกการทำให้ใช้งานได้แบบโหนดเดียว แต่คุณก็จะมีสำเนา 3 รายการผ่านตัวจำลอง R/W 3 รายการ นอกจากนี้ แม้จะมีการกำหนดค่าการติดตั้งใช้งานระดับภูมิภาค คุณก็ยังขยายการใช้งานได้โดยมีสำเนาแบบอ่านอย่างเดียวเพิ่มเติมในโทโพโลยีการติดตั้งใช้งาน

เมื่อกำหนดค่าความจุแล้ว คุณจะเริ่มต้นที่โหนดแบบเต็มและปรับขนาดอัตโนมัติที่โหนด หรือจะใช้อินสแตนซ์แบบละเอียด (หน่วยประมวลผล 1, 000 PU = 1 โหนด) ก็ได้ นอกจากนี้ คุณยังตั้งเป้าหมายการปรับขนาดอัตโนมัติของอินสแตนซ์ได้ด้วย (ไม่บังคับ) สำหรับภาระงานที่มีเวลาในการตอบสนองต่ำ เราขอแนะนำให้ใช้ 65% สำหรับอินสแตนซ์ระดับภูมิภาค และ 45% สำหรับอินสแตนซ์แบบหลายภูมิภาค

6325a8561bbc61c7.png

ขั้นตอนที่ 3: สร้างฐานข้อมูล

เมื่อจัดสรรอินสแตนซ์แล้ว ให้คลิก "สร้างฐานข้อมูล" เพื่อสร้างฐานข้อมูลสำหรับส่วนที่เหลือของโค้ดแล็บ

422b0317859ec7df.png

การสร้างรากฐานความสัมพันธ์

การเดินทางของเราเริ่มต้นด้วยตารางหลักที่จัดเก็บข้อมูลการดำเนินงาน ใน Cloud Spanner เราใช้การสอดแทรกเพื่อจัดเก็บข้อมูลที่เกี่ยวข้องไว้ด้วยกัน เช่น ความสัมพันธ์และธุรกรรมของลูกค้าจะจัดเก็บไว้กับบันทึกลูกค้าโดยตรง ซึ่งจะช่วยให้มั่นใจได้ว่าการเข้าถึงและสถานที่ตั้งจริงมีประสิทธิภาพสูง

DDL: การสร้างตาราง

คัดลอกและเรียกใช้บล็อกต่อไปนี้เพื่อสร้างสคีมาเชิงสัมพันธ์

-- NODE: Customer (Parent)
CREATE TABLE Customer (
  customer_id STRING(60) NOT NULL,
  customer_email STRING(32),

  -- Placeholder fields for Algorithm results
  pagerank_score FLOAT64,        
  centrality_score FLOAT64,      
  community_id INT64            
) PRIMARY KEY(customer_id);

-- EDGE: CustomerFriendship (Interleaved in Customer)
CREATE TABLE CustomerFriendship (
  customer_id STRING(60) NOT NULL,
  friend_id STRING(60) NOT NULL,
  friendship_strength FLOAT64,
  created_at TIMESTAMP,
  CONSTRAINT FK_Friend FOREIGN KEY(friend_id) REFERENCES Customer(customer_id)
) PRIMARY KEY(customer_id, friend_id),
  INTERLEAVE IN PARENT Customer ON DELETE CASCADE;

-- NODE: Product
CREATE TABLE Product (
  product_id STRING(60) NOT NULL,
  product_name STRING(32),
  unit_price FLOAT64,
  pagerank_score FLOAT64
) PRIMARY KEY(product_id);

-- NODE: Shipping
CREATE TABLE Shipping (
  shipping_id STRING(60) NOT NULL,
  city STRING(32),
  country STRING(32)
) PRIMARY KEY(shipping_id);

-- EDGE: Transactions (Interleaved in Customer)
CREATE TABLE Transactions (
  customer_id STRING(60) NOT NULL,
  row_id STRING(36) DEFAULT (GENERATE_UUID()),
  product_id STRING(60) NOT NULL,
  shipping_id STRING(60) NOT NULL,
  transaction_date TIMESTAMP,
  amount FLOAT64,
  CONSTRAINT FK_Prod FOREIGN KEY(product_id) REFERENCES Product(product_id),
  CONSTRAINT FK_Ship FOREIGN KEY(shipping_id) REFERENCES Shipping(shipping_id)
) PRIMARY KEY(customer_id, row_id),
  INTERLEAVE IN PARENT Customer ON DELETE CASCADE;

การเริ่มต้นเครือข่าย

เมื่อตารางพร้อมแล้ว เราต้องป้อนข้อมูลผู้ใช้ ผลิตภัณฑ์ และการเชื่อมต่อที่กำหนดระบบนิเวศของลูกค้า

-- Populate Products & Shipping
INSERT INTO Product (product_id, product_name, unit_price) VALUES
('P1', 'Smartphone Pro', 999.00), ('P2', 'Wireless Earbuds', 150.00),
('P3', 'USB-C Cable', 25.00), ('P4', '4K Monitor', 450.00),
('P5', 'Ergonomic Chair', 300.00), ('P6', 'Desk Lamp', 45.00);

INSERT INTO Shipping (shipping_id, city, country) VALUES
('S1', 'New York', 'USA'), ('S2', 'London', 'UK'), ('S3', 'Tokyo', 'Japan'),
('S4', 'San Francisco', 'USA'), ('S5', 'Berlin', 'Germany');

-- Populate Customers
INSERT INTO Customer (customer_id, customer_email) VALUES
('C1', 'alice@example.com'), ('C2', 'bob@example.com'), ('C3', 'charlie@example.com'),
('C4', 'david@example.com'), ('C5', 'eve@example.com'), ('C6', 'frank@example.com'),
('C7', 'grace@example.com'), ('C8', 'heidi@example.com'), ('C9', 'ivan@example.com'),
('C10', 'judy@example.com'), ('C11', 'mallory@example.com'), ('C12', 'trent@example.com');

-- Populate Friendships
INSERT INTO CustomerFriendship (customer_id, friend_id, friendship_strength, created_at) VALUES
('C1', 'C2', 1.0, CURRENT_TIMESTAMP()), ('C1', 'C3', 1.0, CURRENT_TIMESTAMP()), 
('C2', 'C1', 0.8, CURRENT_TIMESTAMP()), ('C3', 'C1', 0.9, CURRENT_TIMESTAMP()),
('C3', 'C4', 0.5, CURRENT_TIMESTAMP()), ('C4', 'C5', 0.5, CURRENT_TIMESTAMP()),
('C5', 'C6', 1.0, CURRENT_TIMESTAMP()), ('C5', 'C7', 0.8, CURRENT_TIMESTAMP()), 
('C7', 'C8', 0.7, CURRENT_TIMESTAMP()), ('C8', 'C5', 0.6, CURRENT_TIMESTAMP()),
('C11', 'C1', 1.0, CURRENT_TIMESTAMP()), ('C11', 'C5', 1.0, CURRENT_TIMESTAMP()), 
('C11', 'C7', 1.0, CURRENT_TIMESTAMP()), ('C11', 'C12', 0.5, CURRENT_TIMESTAMP()),
('C1', 'C11', 0.9, CURRENT_TIMESTAMP()), ('C5', 'C11', 0.9, CURRENT_TIMESTAMP()),
('C9', 'C10', 1.0, CURRENT_TIMESTAMP()), ('C10', 'C9', 1.0, CURRENT_TIMESTAMP());

-- Populate Transactions
INSERT INTO Transactions (customer_id, product_id, shipping_id, amount, transaction_date) VALUES
('C1', 'P1', 'S1', 999.00, CURRENT_TIMESTAMP()), ('C2', 'P1', 'S1', 999.00, CURRENT_TIMESTAMP()),
('C11', 'P4', 'S4', 450.00, CURRENT_TIMESTAMP()), ('C11', 'P5', 'S4', 300.00, CURRENT_TIMESTAMP()),
('C7', 'P5', 'S5', 300.00, CURRENT_TIMESTAMP()), ('C8', 'P6', 'S5', 45.00, CURRENT_TIMESTAMP()),
('C9', 'P1', 'S1', 999.00, CURRENT_TIMESTAMP()), ('C10', 'P1', 'S1', 999.00, CURRENT_TIMESTAMP());

ความท้าทายด้านความสัมพันธ์

ก่อนที่จะแนะนำกราฟ เรามาดูกันว่า SQL แบบดั้งเดิมจัดการกับความท้าทายของลูกค้าอย่างไร เรียกใช้คําค้นหานี้เพื่อค้นหาลูกค้า "นักช็อปโซเชียล" ที่ใช้จ่ายอย่างมากและมีเพื่อนหลายคน

SELECT 
    c.customer_id, 
    c.customer_email,
    SUM(t.amount) AS total_spent,
    COUNT(DISTINCT f.friend_id) AS friend_count
FROM Customer AS c
LEFT JOIN Transactions AS t ON c.customer_id = t.customer_id
LEFT JOIN CustomerFriendship AS f ON c.customer_id = f.customer_id
GROUP BY c.customer_id, c.customer_email
HAVING total_spent > 500
ORDER BY total_spent DESC;

ข้อจำกัดของแนวทางเชิงสัมพันธ์

การเอาชนะความท้าทายด้านความสัมพันธ์ผ่านกราฟพร็อพเพอร์ตี้

เราจึงกำหนดกราฟพร็อพเพอร์ตี้เพื่อแก้ปัญหาข้อจำกัดเหล่านี้ ซึ่งจะสร้าง "การซ้อนทับ" ที่ช่วยให้เราถือว่าความสัมพันธ์เป็นสิ่งสำคัญอันดับแรกโดยไม่ต้องย้ายข้อมูลออกจาก Spanner

DDL: การสร้างกราฟพร็อพเพอร์ตี้

DDL นี้กำหนดโหนด (เอนทิตี) และขอบ (ความสัมพันธ์) ในตัวอย่างนี้ เราใช้กราฟที่กำหนดสคีมา แต่ Spanner Graph อนุญาตให้สร้างโมเดลกราฟที่ไม่มีสคีมาเพื่อเปิดใช้การพัฒนาแบบวนซ้ำที่รวดเร็วและยืดหยุ่น รวมถึงจัดการโมเดลข้อมูลที่เปลี่ยนแปลงไปโดยไม่ต้องเปลี่ยนแปลงภาษานิยามข้อมูล (Data Definition Language) อย่างต่อเนื่อง

CREATE OR REPLACE PROPERTY GRAPH RetailTransactionGraph
NODE TABLES (
  Customer KEY (customer_id),
  Product KEY (product_id),
  Shipping KEY (shipping_id)
)
EDGE TABLES (
  CustomerFriendship AS IsFriendsWith
    SOURCE KEY (customer_id) REFERENCES Customer (customer_id)
    DESTINATION KEY (friend_id) REFERENCES Customer (customer_id)
    LABEL IsFriendsWith,
    
  Transactions AS Purchased
    SOURCE KEY (customer_id) REFERENCES Customer (customer_id)
    DESTINATION KEY (product_id) REFERENCES Product (product_id)
    LABEL Purchased,

  Transactions AS LivesAt
    SOURCE KEY (customer_id) REFERENCES Customer (customer_id)
    DESTINATION KEY (shipping_id) REFERENCES Shipping (shipping_id)
    LABEL LivesAt
);

เมื่อกำหนดกราฟแล้ว เราจะใช้ Graph Query Language (GQL) เพื่อดำเนินการข้ามหลายฮอปด้วยไวยากรณ์ที่เรียบง่ายและอ่านง่ายได้

การสำรวจที่ 1: การค้นพบร่วมกัน

คําค้นหานี้จะข้ามกราฟเพื่อค้นหาผลิตภัณฑ์ที่เพื่อนของคุณซื้อและทําหน้าที่เป็นพื้นฐานของเครื่องมือแนะนํา

GRAPH RetailTransactionGraph
MATCH (me:Customer)-[:IsFriendsWith]->(friend:Customer)-[:Purchased]->(p:Product)
WHERE me.customer_id = 'C1'
RETURN 
    me.customer_id AS my_id, 
    friend.customer_id AS friend_id, 
    p.product_name AS recommendation

การสำรวจ 2: การค้นหาแบบไฮบริด (เชิงสัมพันธ์ + กราฟ)

Spanner ช่วยให้คุณฝังรูปแบบ GQL ไว้ในคําสั่ง FROM ของ SQL มาตรฐานได้โดยใช้ฟังก์ชัน GRAPH_TABLE คําค้นหานี้จะค้นหาลูกค้าที่อาศัยอยู่ในสถานที่เดียวกันกับเพื่อน ซึ่งเป็นการจับคู่รูปแบบ "เพชร"

SELECT *
FROM GRAPH_TABLE(RetailTransactionGraph
  MATCH (a:Customer)-[:IsFriendsWith]-(b:Customer),
        (a)-[:LivesAt]->(loc:Shipping),
        (b)-[:LivesAt]->(loc)
  RETURN a.customer_id AS user_A, b.customer_id AS user_B, loc.city
)

การแสดงภาพการเชื่อมต่อของลูกค้า

สุดท้ายนี้ มาใช้ GQL เพื่อแสดงภาพเครือข่ายกัน คำค้นหาเหล่านี้จะรวมผลลัพธ์เส้นทางไว้ใน SAFE_TO_JSON ซึ่งช่วยให้โปรแกรมแสดงภาพวาดโหนดและเส้นได้

การแสดงภาพ Super-Influencer

ซึ่งไฮไลต์ Mallory (C11) และการเข้าถึงโซเชียลโดยตรงของเธอ

GRAPH RetailTransactionGraph
MATCH p = (c:Customer {customer_id: 'C11'})-[:IsFriendsWith]->(f:Customer)
RETURN SAFE_TO_JSON(p) AS social_paths

f0c713fc048cd0a5.png

การแสดงภาพรูปแบบการฉ้อโกงที่อาจเกิดขึ้น

คำค้นหานี้จะค้นหา "คลัสเตอร์ที่แยกกัน" (Ivan และ Judy) เพื่อดูว่ามีการจัดส่งผลิตภัณฑ์ไปยังที่ใด

GRAPH RetailTransactionGraph
MATCH p = (c:Customer)-[:Purchased]->(prod:Product),
      q = (c)-[:LivesAt]->(loc:Shipping)
WHERE c.customer_id IN ('C9', 'C10')
RETURN SAFE_TO_JSON(p) AS purchase_path, SAFE_TO_JSON(q) AS shipping_path

3. ข้อมูลเบื้องต้นเกี่ยวกับอัลกอริทึมกราฟ Spanner

ส่วนนี้จะอธิบายสถาปัตยกรรมทางเทคนิคและกฎพื้นฐานของอัลกอริทึมกราฟของ Cloud Spanner เพื่อเตรียมพร้อมสำหรับการเจาะลึกข้อมูลเกี่ยวกับ Graph Intelligence การทำความเข้าใจหลักการเหล่านี้เป็นกุญแจสำคัญในการเปลี่ยนจากการสำรวจแบบง่ายๆ ไปเป็นการวิเคราะห์ความสัมพันธ์ระดับเพตะไบต์

พอร์ตโฟลิโออัลกอริทึม

ปัจจุบัน Cloud Spanner รองรับอัลกอริทึมกราฟมาตรฐานอุตสาหกรรม 14 รายการ ซึ่งจัดหมวดหมู่เป็น 4 กลุ่มฟังก์ชันเพื่อแก้ปัญหาทางธุรกิจที่หลากหลาย ดังนี้

หมวดหมู่

อัลกอริทึมที่รองรับ

กรณีการใช้งานทางธุรกิจ

ความเป็นศูนย์กลาง

เพจแรงก์ เพจแรงก์ที่ปรับเปลี่ยนในแบบของคุณ ความเป็นสื่อกลาง ความใกล้ชิด

ระบุอินฟลูเอนเซอร์ ฮับ และคอขวด

ชุมชน

WCC, การเผยแพร่ป้ายกำกับ, การค้นหากลุ่ม, การจัดกลุ่มความสัมพันธ์

ตรวจหาเครือข่ายการประพฤติมิชอบ ชุมชนโซเชียล และไซโล

ความคล้ายคลึง

Jaccard, Cosine, เพื่อนบ้านร่วมกัน, เพื่อนบ้านทั้งหมด

ขับเคลื่อนเครื่องมือแนะนำและการแก้ปัญหาเอนทิตี

การค้นหาเส้นทาง

เส้นทางที่สั้นที่สุดจากชุดหนึ่งไปยังอีกชุดหนึ่ง ตัวช่วยเส้นทาง GA

เพิ่มประสิทธิภาพด้านโลจิสติกส์และความใกล้เคียงของการเดินทาง

ข้อควรพิจารณาที่สำคัญเกี่ยวกับสคีมาและการค้นหา

Spanner Graph ต้องปฏิบัติตามกฎต่อไปนี้เพื่อให้มั่นใจว่าอัลกอริทึมกราฟจะทำงานได้อย่างมีประสิทธิภาพ

ข้อกำหนด 1 การจัดวางข้อมูลจริง (การสลับ)

ข้อกำหนดที่สำคัญที่สุดสำหรับการสำรวจกราฟที่มีประสิทธิภาพสูงคือการสลับ ซึ่งจะช่วยให้มั่นใจได้ว่าข้อมูลที่ขอบจะจัดเก็บไว้ในเซิร์ฟเวอร์เดียวกันกับโหนดต้นทาง ซึ่งจะช่วยลดเวลาในการตอบสนองของเครือข่ายระหว่างการเรียกใช้อัลกอริทึม

  • กฎ: ตารางขอบต้องสลับกันในตารางโหนดต้นทาง
  • การข้ามไปข้างหน้า: การแทรกตารางขอบลงในตารางโหนดต้นทางจะช่วยให้มั่นใจได้ว่าแคชจะอยู่ใกล้กับลิงก์ขาออก
  • การย้อนกลับ: ใช้คีย์นอกเพื่อสร้างดัชนีสนับสนุนโดยอัตโนมัติ หรือสร้างดัชนีรองที่สอดแทรกในตารางปลายทาง เพื่อการวิเคราะห์ลิงก์ "ขาเข้า" ที่มีประสิทธิภาพ

ข้อกำหนดที่ 2 ข้อกำหนดในการติดป้ายกำกับที่ไม่ซ้ำกัน

ทุกตารางที่เข้าร่วมในกราฟพร็อพเพอร์ตี้ต้องมีข้อมูลประจำตัวที่ไม่ซ้ำกัน อัลกอริทึมใช้ป้ายกำกับเหล่านี้เพื่อระบุและโหลดกราฟย่อยที่จำเป็นต่อการวิเคราะห์ได้อย่างถูกต้อง

  • กฎ: ตารางอินพุตแต่ละตารางต้องมีป้ายกำกับที่ระบุตัวตนที่ไม่ซ้ำกันภายในกราฟพร็อพเพอร์ตี้
  • ข้อขัดแย้ง: คุณไม่สามารถแมปป้ายกำกับเดียวกับหลายตารางได้หากต้องการเรียกใช้อัลกอริทึมในตารางเหล่านั้น

ตรรกะ

ตัวอย่าง

ผลลัพธ์

❌ ไม่ดี

ตารางโหนด (เอนทิตีป้ายกำกับบุคคล, เอนทิตีป้ายกำกับบัญชี)

ไม่ถูกต้อง: อัลกอริทึมแยกความแตกต่างระหว่างบุคคลกับบัญชีไม่ได้

✅ ดี

ตารางโหนด (ป้ายกำกับบุคคล ลูกค้า, ป้ายกำกับบัญชี บัญชี)

ถูกต้อง: แต่ละเอนทิตีมีป้ายกำกับที่ไม่ซ้ำกัน

ข้อกำหนดที่ 3 โครงสร้างการค้นหาอัลกอริทึม (อนุประโยค MATCH)

เมื่อเรียกใช้อัลกอริทึม อนุประโยค MATCH จะปฏิบัติตามกฎที่เข้มงวดกว่าคำค้นหา GQL มาตรฐานเพื่อให้มั่นใจว่าเครื่องมือการดำเนินการจะเพิ่มประสิทธิภาพไปป์ไลน์การวิเคราะห์ได้

  • รูปแบบ 1 รูปแบบต่อการจับคู่ 1 ครั้ง: แต่ละคำสั่ง MATCH จะตั้งชื่อตัวแปรได้เพียง 1 ตัว
  • ไม่มีรูปแบบหลายโหนด: คุณไม่สามารถกำหนดรูปแบบความสัมพันธ์ (เช่น (a)-[e]->(b)) โดยตรงภายในส่วนคำสั่ง MATCH ที่มีไว้สำหรับการเรียกอัลกอริทึม
  • ตัวกรองตามตัวอักษรเท่านั้น: แม้ว่าคุณจะใช้คําสั่ง WHERE เพื่อกรองโหนดได้ (เช่น WHERE a.id > 400) แต่ระบบไม่รองรับพารามิเตอร์การค้นหา (@param) ในการค้นหาอัลกอริทึมกราฟในขณะนี้

ข้อกำหนดที่ 4 The RETURN Clause (Scalars Only)

โดยในคำค้นหาอัลกอริทึม อนุประโยค RETURN จะทำหน้าที่เป็นตัวเชื่อมระหว่างโลกของกราฟกับโลกของความสัมพันธ์ โดยจะจำกัดไว้เฉพาะการคืนค่าสเกลาร์และค่าคงที่เท่านั้น

  • กฎ: คุณไม่สามารถส่งคืน "องค์ประกอบกราฟ" (ออบเจ็กต์โหนดหรือขอบดิบ)
  • ไม่มีการแปลง: คุณไม่สามารถดำเนินการทางคณิตศาสตร์หรือใช้ฟังก์ชันกับพร็อพเพอร์ตี้ที่ส่งคืนภายในคำสั่ง RETURN เองได้

ข้อจำกัดของข้อกำหนดการคืนสินค้า

✅ รองรับ

❌ ไม่รองรับ

RETURN node.id, score

โหนด RETURN, คะแนน (ไม่สามารถคืนค่าองค์ประกอบกราฟ)

RETURN PATH_LENGTH(p)

RETURN node.id + 1, score (ไม่มีการดำเนินการในพร็อพเพอร์ตี้)

RETURN node.name

RETURN JSON_OBJECT(node.id, score) (ไม่มีฟังก์ชัน)

ข้อกำหนด 5 ความสมบูรณ์ของข้อมูล: การกำจัดขอบที่ค้างอยู่

"ขอบที่ค้าง" จะเกิดขึ้นเมื่อขอบชี้ไปยังโหนดปลายทางที่ไม่มีอยู่ในกราฟ ซึ่งจะทำให้การเรียกใช้อัลกอริทึมล้มเหลวเนื่องจากโครงสร้างกราฟไม่สอดคล้องกัน

  • วิธีแก้ปัญหา: ใช้ข้อจำกัดอ้างอิง (คีย์นอก) และ ON DELETE CASCADE เพื่อรักษาความสมบูรณ์ของกราฟ
  • ความปลอดภัยของคําค้นหา: เมื่อเรียกใช้อัลกอริทึม คุณต้องตรวจสอบว่าโหนดทั้งหมดที่ขอบที่เลือกอ้างอิงรวมอยู่ในอาร์กิวเมนต์ node_labels ด้วย

เอาต์พุตแบบถาวร: ตัวเลือกการส่งออกข้อมูล

เนื่องจากอัลกอริทึมกราฟต้องใช้การคำนวณจำนวนมาก จึงจะดำเนินการในโหมดการดำเนินการแบบเพิ่มขนาดโดยใช้คำสั่ง EXPORT DATA ซึ่งใช้ประโยชน์จาก Data Boost โดยใช้ทรัพยากรการประมวลผลแบบไร้เซิร์ฟเวอร์อิสระเพื่อป้องกันไม่ให้เกิดความล่าช้าในธุรกรรมการผลิต

ตัวเลือกที่ 1: คงข้อมูลกลับไปยัง Cloud Spanner

หากต้องการส่งผลลัพธ์กลับไปยังตารางโดยตรง (เช่น บันทึกคะแนนเพจแรงก์) ให้ใช้ format = ‘CLOUD_SPANNER'

  • update_ignore_all: อัปเดตเฉพาะแถวสำหรับคีย์ที่มีอยู่ในตารางเป้าหมายอยู่แล้ว
  • upsert_ignore_all: อัปเดตแถวที่มีอยู่หรือแทรกแถวใหม่หากไม่มีคีย์
EXPORT DATA OPTIONS (
  format = 'CLOUD_SPANNER',
  table = 'Customer',
  write_mode = 'update_ignore_all'
) AS
GRAPH RetailTransactionGraph
CALL PageRank(...)
RETURN node.customer_id, score;

ตัวเลือกที่ 2: จัดเก็บผลลัพธ์ไว้ใน Google Cloud Storage (GCS)

สำหรับการวิเคราะห์แบบออฟไลน์ในวงกว้าง คุณสามารถส่งออกไปยัง GCS ในรูปแบบ CSV, Avro หรือ Parquet ได้

  • ไวลด์การ์ด: ใช้ uri => 'gs://bucket/file_*.csv' เพื่อเปิดใช้เอาต์พุตที่แยกส่วน ซึ่งจะช่วยให้ Spanner เขียนไปยังหลายไฟล์พร้อมกันสำหรับชุดข้อมูลขนาดใหญ่ได้
  • การบีบอัด: รองรับ GZIP, SNAPPY และ ZSTD เพื่อเพิ่มประสิทธิภาพต้นทุนในการจัดเก็บข้อมูล
EXPORT DATA OPTIONS (
  uri = 'gs://bucket/pagerank_*.csv',
  format = 'CSV',
  overwrite = true
) AS
GRAPH RetailTransactionGraph
CALL PageRank(...)
RETURN node.customer_id, score;

4. ความท้าทายที่ 1: ช่องว่างของอิทธิพล (PageRank)

ในส่วนนี้ เราจะมาพูดถึงอุปสรรคทางธุรกิจแรกของลูกค้า นั่นคือ "ช่องว่างของอิทธิพล" เราจะเปลี่ยนจากการ "ประกวดความนิยม" ขั้นพื้นฐานไปเป็นแผนที่อิทธิพลทางสังคมที่แท้จริงซึ่งขับเคลื่อนด้วยคณิตศาสตร์

คำชี้แจงปัญหา: ทีมการตลาดของลูกค้ามีปัญหา โดยใช้เงินหลายล้านไปกับการโฆษณาแบบกว้างๆ ที่ให้ผลตอบแทนลดลงเนื่องจากไม่สามารถระบุ "ซูเปอร์สตาร์โซเชียล" ซึ่งเป็นบุคคลหายากที่การรับรองของบุคคลนั้นๆ ส่งผลต่อทั้งเครือข่าย

หากต้องการแก้ปัญหานี้ เราต้องจัดอันดับลูกค้าตามอิทธิพล

โซลูชันเชิงสัมพันธ์ (Degree Centrality)

ในฐานข้อมูลมาตรฐาน วิธีที่ง่ายที่สุดในการค้นหาอินฟลูเอนเซอร์คือการนับผู้ติดตาม (เมตริกที่เรียกว่าDegree Centrality)

เรียกใช้การค้นหานี้เพื่อค้นหาผู้ใช้ที่ "ได้รับความนิยม" มากที่สุด

SELECT 
    friend_id AS customer_id, 
    COUNT(*) AS follower_count
FROM CustomerFriendship
GROUP BY friend_id
ORDER BY follower_count DESC;

customer_id

follower_count

C1

3

C5

3

C11

2

C7

2

C10

1

C12

1

C2

1

C3

1

C4

1

C6

1

C8

1

C9

1

ข้อมูลวิเคราะห์กราฟ (PageRank)

เราใช้ PageRank เพื่อค้นหาผู้นำที่แท้จริง อัลกอริทึมนี้เป็นอัลกอริทึมเดียวกับที่ใช้ในการค้นเว็บในช่วงแรก โดยจะวัดความสำคัญของโหนดตามปริมาณและคุณภาพของลิงก์ขาเข้า

  • โมเดลการท่องเว็บแบบสุ่ม: PageRank จำลองผู้ใช้ที่เคลื่อนที่ผ่านกราฟ ปัจจัยการลดทอน (ค่าเริ่มต้นคือ 0.85) แสดงถึงความน่าจะเป็นที่ผู้ใช้จะคลิกต่อไป มิเช่นนั้นผู้ใช้จะ "เทเลพอร์ต" ไปยังโหนดแบบสุ่ม
  • พลังแห่งการเชื่อมโยง: ลิงก์จากผู้มีอิทธิพล (เช่น Mallory) มีค่ามากกว่าลิงก์จากผู้ที่ไม่มีการเชื่อมต่ออื่นๆ อย่างมาก

เราจะเรียกใช้อัลกอริทึม PageRank และใช้ EXPORT DATA เพื่อบันทึกผลลัพธ์ลงในคอลัมน์ pagerank_score โดยตรง

EXPORT DATA OPTIONS (
  format = 'CLOUD_SPANNER',
  table = 'Customer',
  write_mode = 'update_ignore_all' -- Updates existing rows
) AS
GRAPH RetailTransactionGraph
CALL PageRank(
  node_labels => ['Customer'],      -- Target our Customer nodes 
  edge_labels => ['IsFriendsWith'], -- Analyze the social ties
  damping_factor => 0.85,           -- Standard decay
  max_iterations => 10              -- Higher iterations for better precision
)
YIELD node, score               
RETURN node.customer_id, score as pagerank_score;

แดชบอร์ด"อิทธิพล" โดยใช้ PageRank

ตอนนี้เราได้บันทึกคะแนนไว้แล้ว มาเปรียบเทียบ "ก่อน" (จำนวนผู้ติดตาม) กับ "หลัง" (คะแนนเพจแรงก์) กัน

-- Note that Higher PageRank score means more influential
SELECT 
    c.customer_id, 
    c.customer_email,
    count_query.follower_count,
    c.pagerank_score
FROM Customer c
JOIN (
    SELECT friend_id, COUNT(*) AS follower_count 
    FROM CustomerFriendship GROUP BY friend_id
) AS count_query ON c.customer_id = count_query.friend_id
ORDER BY c.pagerank_score DESC;

customer_id

customer_email

follower_count

pagerank_score

C5

eve@example.com

3

0.158392489

C10

judy@example.com

1

0.1093561724

C9

ivan@example.com

1

0.1093561724

C1

alice@example.com

3

0.1000888124

C8

heidi@example.com

1

0.09759821743

C11

mallory@example.com

2

0.09466411918

C7

grace@example.com

2

0.08016719669

C6

frank@example.com

1

0.06022448093

C2

bob@example.com

1

0.0547891818

C3

charlie@example.com

1

0.0547891818

C12

trent@example.com

1

0.04029225558

C4

david@example.com

1

0.04028172791

การวิเคราะห์: ใครคือซูเปอร์สตาร์ตัวจริง

การวิเคราะห์ผลลัพธ์จะช่วยให้คุณค้นพบข้อมูลทางการตลาดที่สำคัญ 3 อย่างต่อไปนี้

สิ่งที่ธุรกิจควรทราบ

ตอนนี้ทีมการตลาดของลูกค้าสามารถมุ่งเน้นเฉพาะผู้ที่มี pagerank_score สูงสุดได้แล้ว แทนที่จะส่งอีเมลถึงทุกคนที่มีผู้ติดตามมากกว่า 5 คนโดยไม่เลือก บุคคลเหล่านี้คือ "ซูเปอร์สตาร์โซเชียล" ตัวจริงที่สามารถขับเคลื่อนการแชร์แบบไวรัลในระบบทั่วทั้งมาร์เก็ตเพลส

ตอนนี้เรามาลองระบุผู้ดูแลที่ทำให้เครือข่ายโลจิสติกส์ของลูกค้าทำงานต่อไปได้

5. ความท้าทายที่ 2: ความยืดหยุ่นด้านโลจิสติกส์ (BetweennessCentrality)

ในส่วนนี้ เราจะพูดถึงความยืดหยุ่นด้านโลจิสติกส์ เราจะก้าวข้ามการวัดความสำเร็จด้วย "ปริมาณ" ไปสู่การระบุ "ผู้ดูแล" ที่สำคัญซึ่งทำให้เครือข่ายเชื่อมต่อกันอยู่

โซลูชันเชิงสัมพันธ์ (การวิเคราะห์ตามปริมาณ)

ในการตั้งค่าเชิงสัมพันธ์มาตรฐาน โดยทั่วไปแล้วฮับการจัดส่งที่ "สำคัญ" จะกำหนดเป็นฮับที่ประมวลผลคำสั่งซื้อมากที่สุดหรือสร้างรายได้มากที่สุด

เรียกใช้การค้นหานี้เพื่อระบุฮับ "ยอดนิยม" ตามจำนวนธุรกรรม

-- Identify "Critical" hubs by transaction volume
SELECT 
    s.city, 
    s.country, 
    COUNT(t.row_id) AS transaction_count,
    SUM(t.amount) AS total_revenue
FROM Shipping s
JOIN Transactions t ON s.shipping_id = t.shipping_id
GROUP BY s.city, s.country
ORDER BY transaction_count DESC;

city

country

transaction_count

total_revenue

นิวยอร์ก

USA

4

3996

เบอร์ลิน

เยอรมนี

2

345

ซานฟรานซิสโก

USA

2

750

เราจะใช้ทั้งขอบ IsFriendsWith และ LivesAt เพื่อแก้ไขความไม่ตรงกัน ซึ่งจะเปลี่ยนการวิเคราะห์ของเราจากฮับธุรกรรมให้รวมถึงการตรวจสอบทางสังคมด้วย

ข้อมูลวิเคราะห์กราฟ (Centrality ระหว่าง)

เราใช้ค่าความเป็นศูนย์กลางระหว่างเพื่อค้นหาคอขวดที่แท้จริง อัลกอริทึมนี้จะวัดปริมาณความถี่ที่โหนดทำหน้าที่เป็น "สะพาน" ตามเส้นทางที่สั้นที่สุดระหว่างคู่โหนดอื่นๆ ทั้งหมดในกราฟ คะแนนสูงจะระบุผู้ดูแลที่แท้จริงซึ่งควบคุมการไหลเวียนของสินค้าหรือข้อมูล

การเรียกใช้และการคงค่า Betweenness Centrality

เราจะเรียกใช้อัลกอริทึมโดยใช้ EXPORT DATA และบันทึกคะแนนลงในคอลัมน์ centrality_score เราใช้ Data Boost เพื่อให้มั่นใจว่าการคำนวณ "เส้นทางที่สั้นที่สุด" ที่ซับซ้อนนี้จะแทบไม่มีผลกระทบต่อการดำเนินงานจริงของลูกค้า

EXPORT DATA OPTIONS (
  format = 'CLOUD_SPANNER',
  table = 'Customer',
  write_mode = 'update_ignore_all' 
) AS
GRAPH RetailTransactionGraph
CALL BetweennessCentrality(
  -- We include both Customer and Shipping nodes for a full ecosystem view
  node_labels => ['Customer', 'Shipping'], 
  -- We factor in social ties AND physical shipping locations
  edge_labels => ['IsFriendsWith', 'LivesAt'], 
  num_source_nodes => 100
)
YIELD node, score
-- We only persist scores for Customers; Shipping node results are safely ignored
RETURN node.customer_id, score as centrality_score;

การวิเคราะห์: การระบุ "คอขวดที่ซ่อนอยู่"

ตอนนี้เราจะเปรียบเทียบความเสี่ยงเชิงโครงสร้าง (centrality_score) กับปริมาณธุรกรรม (order_count) เพื่อค้นหาโหนดที่ผู้นำของลูกค้าควรเป็นกังวล

SELECT 
    c.customer_id, 
    c.customer_email,
    c.centrality_score,
    count_query.order_count
FROM Customer c
LEFT JOIN (
    SELECT customer_id, COUNT(*) AS order_count 
    FROM Transactions GROUP BY customer_id
) AS count_query ON c.customer_id = count_query.customer_id
ORDER BY c.centrality_score DESC;

customer_id

customer_email

centrality_score

order_count

C11

mallory@example.com

44.5

2

C1

alice@example.com

35.5

1

C5

eve@example.com

35.5

C7

grace@example.com

12

1

C8

heidi@example.com

10

1

C3

charlie@example.com

6

C4

david@example.com

3.5

C10

judy@example.com

0

1

C12

trent@example.com

0

C2

bob@example.com

0

1

C6

frank@example.com

0

C9

ivan@example.com

0

1

จากการวิเคราะห์ผลลัพธ์เหล่านี้ ลูกค้าได้ค้นพบสิ่งที่น่าตกใจ 3 อย่าง

ข้อคิดทางธุรกิจ

ตอนนี้ลูกค้าสามารถจัดลำดับความสำคัญของโปรโตคอลความซ้ำซ้อนด้านลอจิสติกส์และความปลอดภัยตามความเสี่ยงเชิงโครงสร้างแบบหลายรูปแบบได้แล้ว Mallory, Alice และ Eve เป็นผู้ดูแลประตูที่ต้องได้รับการปกป้องเพื่อให้มั่นใจถึงความเสถียรของเครือข่ายลอจิสติกส์

ตอนนี้เรามาลองแยกเกาะการฉ้อโกงกัน

6. ความท้าทายที่ 3: เครือข่ายผี (WCC)

ในส่วนนี้ เราจะมาจัดการกับอุปสรรคทางธุรกิจที่ 3 นั่นคือ "เครือข่ายผี" เราจะเปลี่ยนจากการตรวจหา "ฮอตสปอต" แบบง่ายๆ ไปเป็นการค้นหาเครือข่ายการฉ้อโกงที่ซับซ้อนและแยกกันโดยใช้การตรวจหาชุมชน ความท้าทายในที่นี้คือผู้ไม่ประสงค์ดีสร้างโปรไฟล์ปลอมที่แชร์ที่อยู่สำหรับจัดส่งหรือโต้ตอบในวงปิดเพื่อประสานงานการลักขโมยและเพิ่มการให้คะแนนสินค้า แต่โดยทั่วไปแล้วมิจฉาชีพเหล่านี้มักจะแยกตัวออกจากชุมชน The Customer ที่ถูกต้องโดยสิ้นเชิง

เราต้องเปิดเผย "เกาะที่แยกตัว" เหล่านี้เพื่อแก้ปัญหานี้

หากไม่มีอัลกอริทึมกราฟ วิธีมาตรฐานในการตรวจหาการฉ้อโกงคือการมองหา "ฮอตสปอต" ของข้อมูลที่แชร์ เช่น ลูกค้าหลายรายจัดส่งไปยังที่อยู่เดียวกัน

เรียกใช้การค้นหานี้เพื่อค้นหาลูกค้าที่ลิงก์ด้วยสถานที่จัดส่งที่ใช้ร่วมกัน

SELECT 
    shipping_id, 
    COUNT(DISTINCT customer_id) AS customer_count,
    ARRAY_AGG(customer_id) AS linked_customers
FROM Transactions
GROUP BY shipping_id
HAVING customer_count > 1;

shipping_id

customer_count

linked_customers

S1

4

["C1","C10","C2","C9"]

S5

2

["C7","C8"]

หากต้องการค้นหาเครือข่ายการประพฤติมิชอบ เราต้องทำความเข้าใจการเข้าถึงแบบทรานซิทีฟ

Graph Intelligence (Weakly Connected Components)

เราใช้คอมโพเนนต์ที่เชื่อมต่ออย่างหลวมๆ (WCC) เพื่อค้นหาขอบเขตทั้งหมดของวงแหวนเหล่านี้ WCC เป็นอัลกอริทึมการจัดกลุ่มที่ระบุชุดโหนดที่มีเส้นทางระหว่างโหนด 2 โหนดใดๆ โดยไม่คำนึงถึงทิศทางของขอบ

  • โซนที่เข้าถึงได้: โซนนี้จะแบ่งกราฟออกเป็น "เกาะ" หรือ "โซนที่เข้าถึงได้"
  • มุมมองเอนทิตีแบบรวม: การวิเคราะห์ทั้งความสัมพันธ์ทางสังคม (IsFriendsWith) และความสัมพันธ์ด้านโลจิสติกส์ (LivesAt) พร้อมกันช่วยให้เราจัดกลุ่มโปรไฟล์ที่กระจัดกระจายเป็น "คลัสเตอร์อิทธิพล" เดียวแบบรวมได้

การเรียกใช้และการคงอยู่ของ WCC

เราจะเรียกใช้อัลกอริทึม WCC และบันทึกผลลัพธ์ลงในคอลัมน์ community_id เราใช้การเพิ่มข้อมูลเพื่อให้มั่นใจว่าการวิเคราะห์การเข้าถึงเชิงลึกนี้เกิดขึ้นในทรัพยากรการประมวลผลอิสระ

EXPORT DATA OPTIONS (
  format = 'CLOUD_SPANNER',
  table = 'Customer',
  write_mode = 'update_ignore_all' 
) AS
GRAPH RetailTransactionGraph
CALL WeaklyConnectedComponents(
  node_labels => ['Customer', 'Shipping'], 
  edge_labels => ['IsFriendsWith', 'LivesAt']
)
YIELD node, cluster
-- node.customer_id will be NULL for Shipping nodes; 
-- EXPORT DATA will safely ignore those rows.
RETURN node.customer_id, cluster AS community_id;

การวิเคราะห์: เครือข่ายการประพฤติมิชอบ

ตอนนี้มาเรียกใช้การค้นหาการตรวจสอบเพื่อดูชุมชนที่แยกกัน โดยปกติแล้วผู้ใช้ที่ถูกต้องจะอยู่ใน "แผ่นดินใหญ่" ในขณะที่ผู้ฉ้อโกงมักจะติดอยู่บน "เกาะ" เล็กๆ

SELECT 
    community_id, 
    COUNT(*) AS member_count,
    ARRAY_AGG(customer_email) AS members
FROM Customer
GROUP BY community_id
ORDER BY member_count ASC;

community_id

member_count

สมาชิก

1

2

["judy@example.com","ivan@example.com"]

0

10

["alice@example.com","mallory@example.com","trent@example.com","bob@example.com","charlie@example.com","david@example.com","eve@example.com","frank@example.com","grace@example.com","heidi@example.com"]

การเรียกใช้การตรวจหาชุมชนนี้จะช่วยให้คุณระบุความผิดปกติที่สำคัญได้

ข้อคิดทางธุรกิจ

ตอนนี้ลูกค้าสามารถทำให้การตอบสนองด้านความปลอดภัยเป็นแบบอัตโนมัติได้แล้ว แทนที่จะต้องติดตามบัญชีแต่ละบัญชีด้วยตนเอง พวกเขาสามารถเขียนกฎง่ายๆ ได้ว่า "หาก community_id มีสมาชิกน้อยกว่า 3 คน ให้แจ้งกลุ่มทั้งหมดเพื่อรับการตรวจสอบ KYC (Know Your Customer) ด้วยตนเอง"

เมื่อระบุเครือข่ายการประพฤติมิชอบได้แล้ว เราจะแก้ปัญหา "พฤติกรรมที่คล้ายกัน" ได้

7. ความท้าทายที่ 4: Behavioral Twin (JaccardSimilarity)

ในความท้าทายสุดท้ายนี้ เราจะมาพูดถึงอุปสรรคที่ 4 นั่นคือ "Paradox of Choice"/"Behavioral Twin" เราจะเปลี่ยนจากรายการ "ซื้อร่วมกัน" ทั่วไปเป็นคำแนะนำที่ปรับเปลี่ยนในแบบของคุณอย่างยิ่งตาม "ลายนิ้วมือ" ด้านพฤติกรรม

คำแนะนำผลิตภัณฑ์ปัจจุบันของลูกค้าทั่วไปเกินไป การแนะนำสาย USB ที่ได้รับความนิยมให้แก่ลูกค้าทุกคนเป็นเรื่องที่ปลอดภัย แต่ก็ไม่ได้เป็นการแนะนำเฉพาะบุคคล ลูกค้าต้องการสร้างคำแนะนำ "Behavioral Twin" เพื่อระบุลูกค้าที่มีรูปแบบการจัดส่งและวงสังคมที่ไม่เหมือนใคร เพื่อแนะนำผลิตภัณฑ์ที่มีการจับคู่ที่มีความแม่นยำสูง

หากต้องการแก้ปัญหานี้ เราต้องคำนวณ"ความใกล้เคียง"ระหว่างผู้ใช้

โซลูชันเชิงสัมพันธ์ (การทับซ้อนกันโดยสมบูรณ์)

ในการตั้งค่าเชิงสัมพันธ์มาตรฐาน คุณอาจมองหาผู้ที่จัดส่งไปยังสถานที่เดียวกันกับผู้ใช้ที่อ้างอิง เช่น Alice (C1)

เรียกใช้คำค้นหานี้เพื่อค้นหาเพื่อนบ้านทางภูมิศาสตร์ของอลิซ

SELECT 
    t2.customer_id AS similar_customer,
    COUNT(DISTINCT t1.shipping_id) AS shared_locations
FROM Transactions t1
JOIN Transactions t2 ON t1.shipping_id = t2.shipping_id
WHERE t1.customer_id = 'C1' AND t2.customer_id != 'C1'
GROUP BY similar_customer
ORDER BY shared_locations DESC;

similar_customer

shared_locations

C2

1

C10

1

C9

1

Graph Intelligence (ความคล้ายคลึงของ Jaccard)

เราใช้ความคล้ายคลึงแบบ Jaccard เพื่อค้นหาพฤติกรรมที่เหมือนกันอย่างแท้จริง อัลกอริทึมนี้จะคํานวณคะแนนที่ปรับให้เป็นมาตรฐาน (0.0 ถึง 1.0) โดยการหารจํานวนเพื่อนบ้านที่แชร์ (Intersection) ด้วยจํานวนเพื่อนบ้านที่ไม่ซ้ำกันทั้งหมด (Union)

ในที่นี้ "คู่แฝดเชิงพฤติกรรม" ไม่ได้กำหนดจากที่อยู่สำหรับจัดส่งที่ใช้ร่วมกันเท่านั้น การวิเคราะห์จุดตัดของร่องรอยทางกายภาพ (LivesAt) และระบบนิเวศทางสังคม (IsFriendsWith) ช่วยให้เราสามารถระบุผู้ใช้ที่มีไลฟ์สไตล์และอิทธิพลในชุมชนเดียวกัน ซึ่งนำไปสู่คำแนะนำผลิตภัณฑ์ที่แม่นยำยิ่งขึ้น

ก่อนอื่นให้สร้างตารางการแมป

เนื่องจากความคล้ายคลึงกันเป็นความสัมพันธ์แบบคู่ (ลูกค้า ก. คล้ายกับลูกค้า ข.) เราจึงสร้างตารางเฉพาะที่สอดแทรกใน Customer เพื่อจัดเก็บการแมปเหล่านี้

CREATE TABLE CustomerSimilarity (
  customer_id STRING(60) NOT NULL, -- Renamed from source_id to match Parent PK
  target_id STRING(60) NOT NULL,
  similarity_score FLOAT64,
  CONSTRAINT FK_SourceCustomer FOREIGN KEY(customer_id) REFERENCES Customer(customer_id),
  CONSTRAINT FK_TargetCustomer FOREIGN KEY(target_id) REFERENCES Customer(customer_id)
) PRIMARY KEY(customer_id, target_id),
  INTERLEAVE IN PARENT Customer ON DELETE CASCADE;

เรียกใช้ความคล้ายคลึงของ Jaccard

ตอนนี้เราจะรันอัลกอริทึม หมายเหตุ: คำถามนี้มีบทเรียน "แนวทาง" ทั่วไป หากคุณเลือกเฉพาะโหนดลูกค้าแต่ใช้ขอบ LivesAt (ซึ่งชี้ไปยังโหนดการจัดส่ง) การค้นหาจะล้มเหลวโดยอ้างถึง"ขอบที่ค้างอยู่" หากต้องการแก้ไขปัญหานี้ เราต้องใส่ป้ายกำกับโหนดทั้ง 2 รายการ

EXPORT DATA OPTIONS (
  format = 'CLOUD_SPANNER',
  table = 'CustomerSimilarity', 
  write_mode = 'upsert_ignore_all' 
) AS
GRAPH RetailTransactionGraph
CALL JaccardSimilarity(
  node_labels => ['Customer', 'Shipping'], -- Added Shipping to avoid dangling edges
  edge_labels => ['LivesAt', 'IsFriendsWith'], -- Use both logistics and social edges for holistic similarity
  source_nodes => ARRAY(
    SELECT s FROM GRAPH_TABLE(RetailTransactionGraph 
      MATCH (s:Customer {customer_id: 'C1'}) 
      RETURN s)
  ),
  target_nodes => ARRAY(
    SELECT t FROM GRAPH_TABLE(RetailTransactionGraph 
      MATCH (t:Customer) 
      WHERE t.customer_id != 'C1' 
      RETURN t)
  )
)
YIELD source_node, target_node, similarity
RETURN 
    source_node.customer_id AS customer_id, 
    target_node.customer_id AS target_id, 
    similarity AS similarity_score;

การวิเคราะห์: ตรวจสอบ "กลุ่มเป้าหมายตามพฤติกรรม"

เมื่องานวิเคราะห์เสร็จสมบูรณ์แล้ว เราจะเรียกใช้การค้นหาการตรวจสอบ การรวมตารางการแมปใหม่ (CustomerSimilarity) กับข้อมูลเมตา Customer เดิมของเราจะช่วยให้เราเห็นได้อย่างชัดเจนว่าใครคือ "ฝาแฝดด้านพฤติกรรม" ของอลิซ

เรียกใช้การค้นหานี้เพื่อตรวจสอบการจัดอันดับความคล้ายคลึงของอลิซ

SELECT 
    c.customer_email AS peer_email,
    s.similarity_score,
    c.community_id,
    c.pagerank_score
FROM CustomerSimilarity s
JOIN Customer c ON s.target_id = c.customer_id
WHERE s.customer_id = 'C1'
ORDER BY s.similarity_score DESC;

peer_email

similarity_score

community_id

pagerank_score

judy@example.com

0.200000003

1

0.1093561724

bob@example.com

0.200000003

0

0.0547891818

ivan@example.com

0.200000003

1

0.1093561724

eve@example.com

0.1666666716

0

0.158392489

mallory@example.com

0

0

0.09466411918

trent@example.com

0

0

0.04029225558

charlie@example.com

0

0

0.0547891818

david@example.com

0

0

0.04028172791

frank@example.com

0

0

0.06022448093

grace@example.com

0

0

0.08016719669

heidi@example.com

0

0

0.09759821743

สิ่งที่ควรดูในผลลัพธ์

ตอนนี้มาลองสร้างมุมมอง Unified Intelligence สุดท้ายกัน

8. Unified Intelligence

ตอนนี้เราจะเปลี่ยนจากงานด้านเทคนิคแต่ละอย่างไปเป็น Unified Intelligence ในที่นี้ เราจะรวมข้อมูลธุรกรรมเข้ากับอัลกอริทึมกราฟทั้ง 4 รายการเพื่อมอบข้อมูลเชิงลึกที่ชัดเจนและนำไปใช้ได้จริง

รายงานที่ 1: ข้อมูลอัจฉริยะแบบรวม

ความสามารถของฐานข้อมูลแบบหลายโมเดลอย่าง Spanner คือความสามารถในการรวมข้อมูลค่าใช้จ่ายเชิงสัมพันธ์กับคะแนนอิทธิพล ความเสี่ยง และความคล้ายคลึงที่ได้จากกราฟในคำขอเดียว คําค้นหานี้จะจัดหมวดหมู่ลูกค้าทุกคนเป็นลักษณะตัวตนทางธุรกิจที่เฉพาะเจาะจง

เรียกใช้การค้นหา Unified Intelligence เพื่อดูระบบนิเวศที่สมบูรณ์

SELECT 
    c.customer_id,
    c.customer_email,
    -- Transactional Data (Relational)
    COALESCE(t.total_spend, 0) AS spend,
    -- Graph Intelligence Data (Algorithms)
    c.pagerank_score AS influence,
    c.centrality_score AS bottleneck_risk,
    c.community_id,
    -- Persona Categorization Logic
    CASE 
        WHEN c.community_id = 1 THEN '🔴 HIGH RISK: Isolated Fraud Ring'
        WHEN c.centrality_score > 25 THEN '🔵 CRITICAL: Network Bridge'
        WHEN c.pagerank_score > 0.08 AND t.total_spend > 500 THEN ' VIP: Influential Spender'
        WHEN c.pagerank_score > 0.08 THEN '📱 SOCIAL: High-Reach Influencer'
        WHEN sim.similarity_to_alice = 1.0 AND c.community_id != 0 THEN '⚠️ WARNING: Identity Anomaly'
        ELSE '🟢 STANDARD: Active Customer'
    END AS business_persona
FROM Customer c
LEFT JOIN (
    -- Aggregate total spend per customer
    SELECT customer_id, SUM(amount) AS total_spend 
    FROM Transactions GROUP BY customer_id
) t ON c.customer_id = t.customer_id
LEFT JOIN (
    -- Pull similarity relative to our reference user 'C1'
    SELECT target_id, similarity_score AS similarity_to_alice 
    FROM CustomerSimilarity WHERE customer_id = 'C1'
) sim ON c.customer_id = sim.target_id
ORDER BY c.centrality_score DESC, c.pagerank_score DESC;

customer_id

customer_email

ค่าใช้จ่าย

อิทธิพล

bottleneck_risk

community_id

business_persona

C11

mallory@example.com

750

0.09466411918

44.5

0

🔵 วิกฤต: Network Bridge

C5

eve@example.com

0

0.158392489

35.5

0

🔵 วิกฤต: Network Bridge

C1

alice@example.com

999

0.1000888124

35.5

0

🔵 วิกฤต: Network Bridge

C7

grace@example.com

300

0.08016719669

12

0

📱 โซเชียล: อินฟลูเอนเซอร์ที่มีการเข้าถึงสูง

C8

heidi@example.com

45

0.09759821743

10

0

📱 โซเชียล: อินฟลูเอนเซอร์ที่มีการเข้าถึงสูง

C3

charlie@example.com

0

0.0547891818

6

0

🟢 มาตรฐาน: ลูกค้าที่ใช้งานอยู่

C4

david@example.com

0

0.04028172791

3.5

0

🟢 มาตรฐาน: ลูกค้าที่ใช้งานอยู่

C10

judy@example.com

999

0.1093561724

0

1

🔴 ความเสี่ยงสูง: เครือข่ายการประพฤติมิชอบที่แยกกัน

C9

ivan@example.com

999

0.1093561724

0

1

🔴 ความเสี่ยงสูง: เครือข่ายการประพฤติมิชอบที่แยกกัน

C6

frank@example.com

0

0.06022448093

0

0

🟢 มาตรฐาน: ลูกค้าที่ใช้งานอยู่

C2

bob@example.com

999

0.0547891818

0

0

🟢 มาตรฐาน: ลูกค้าที่ใช้งานอยู่

C12

trent@example.com

0

0.04029225558

0

0

🟢 มาตรฐาน: ลูกค้าที่ใช้งานอยู่

การผสมผสานมุมมองทางคณิตศาสตร์เหล่านี้ช่วยให้เราก้าวข้ามคำถามที่ว่า "ใครใช้จ่ายมากที่สุด" ไปสู่คำถามที่ว่า "ใครสำคัญที่สุด" แดชบอร์ดแบบรวมจะผสานรวมข้อมูลธุรกรรมเชิงสัมพันธ์กับข้อมูลเชิงลึกแบบกราฟหลายรูปแบบเพื่อจัดหมวดหมู่ระบบนิเวศของคุณเป็น 3 กลุ่มเป้าหมายที่ชัดเจนและนําไปปฏิบัติได้

"สะพานเครือข่ายที่สำคัญ" (ความยืดหยุ่น)

ระบบจะแจ้งว่าโหนดอย่าง Mallory (C11), Eve (C5) และ Alice (C1) มีความเสี่ยงเนื่องจาก bottleneck_risk (Betweenness Centrality) >25

  • แองเคอร์เชิงโครงสร้าง: Mallory มีคะแนนความเสี่ยงสูงสุดที่ 44.5 ซึ่งทำให้เธอเป็นเกตเวย์หลักสำหรับทั้งเครือข่าย
  • The Zero-Spend Paradox: Eve (C5) มีจำนวนคำสั่งซื้อเป็น 0 แต่มีความสำคัญในเชิงโครงสร้างโดยมีคะแนนความเสี่ยงอยู่ที่ 35.5 SQL มาตรฐานจะละเลยเธอไปโดยสิ้นเชิง แต่ Graph Intelligence เผยให้เห็นว่าเธอเป็นสะพานสำคัญที่เชื่อมโยงไปยังชุมชนย่อยทั้งหมด
  • เกตเวย์ที่มีมูลค่าสูง: อลิซ (C1) มีคะแนนเท่ากับอีฟที่ 35.5 ซึ่งพิสูจน์ให้เห็นว่าผู้ใช้ที่ใช้จ่ายสูงก็เป็นจุดยึดโครงสร้างที่สำคัญได้เช่นกัน

"ซูเปอร์สตาร์โซเชียล" (การเข้าถึง)

Heidi (C8) และ Grace (C7) ได้รับการระบุว่าเป็นอินฟลูเอนเซอร์ที่มีการเข้าถึงสูงเนื่องจากคะแนน PageRank

"วงแหวนการฉ้อโกงที่แยกกัน" (ความผิดปกติ)

ระบบจะแจ้งว่า Judy (C10) และ Ivan (C9) มีความเสี่ยงเนื่องจากอยู่ใน community_id 1 ที่แยกกัน

ข้อมูลเชิงลึกทางธุรกิจเพื่อการดำเนินการเชิงกลยุทธ์

ลักษณะตัวตน

เมตริกหลัก

ข้อมูลเชิงลึกทางธุรกิจ

การดำเนินการเชิงกลยุทธ์

🔵 อุปกรณ์เชื่อมโยงเครือข่าย

High Centrality

จุดยึดโครงสร้าง: อีฟ (C5) และมัลลอรี (C11) เป็นตัวยึดเครือข่าย

การรักษา: ปกป้องผู้ดูแลเหล่านี้เพื่อป้องกันไม่ให้ชุมชนแตกแยก

📱 สุดยอดครีเอเตอร์โซเชียล

เพจแรงก์สูง

เครื่องมือที่ทำให้เกิดการแชร์อย่างรวดเร็ว: ผู้ใช้เช่น Heidi (C8) มีการเข้าถึงสูงสุดในวงสังคมของตน

การตลาด: ใช้สำหรับโปรแกรมแนะนำและโปรแกรมแอมบาสเดอร์ที่มีผลลัพธ์สูง

🔴 ความเสี่ยงในการฉ้อโกง

Isolated WCC

เครือข่ายผี: จูดี้ (C10) และไอแวน (C9) เป็นผู้ใช้ที่ใช้จ่ายสูงแต่ไม่ได้อยู่ในกลุ่มเดียวกัน

ความปลอดภัย: การตรวจสอบ KYC โดยเจ้าหน้าที่ทันที ซึ่งเป็นลายเซ็นการฉ้อโกงแบบคลาสสิก

🟢 ผู้ใช้ทั่วไป

คะแนนที่สมดุล

Healthy Core: เครือข่ายส่วนใหญ่ รวมถึงบริดจ์ "ท้องถิ่น" เช่น David (C4)

การเติบโต: ใช้โฆษณาที่ปรับตามโปรไฟล์ผู้ใช้มาตรฐานและคำแนะนำ "กลุ่มเป้าหมายที่คล้ายกันตามพฤติกรรม"

รายงานที่ 2: รายงานความผิดปกติของข้อมูลระบุตัวตน

ตอนนี้คุณต้องทราบว่ามิจฉาชีพกำลัง "เลียนแบบ" บัญชีที่ถูกต้องหรือไม่ เราสามารถแก้ปัญหานี้ได้โดยการค้นหาผู้ใช้ที่มีความคล้ายคลึงกันด้านพฤติกรรม 100% แต่ไม่มีการเชื่อมต่อทางสังคม

เรียกใช้การค้นหานี้เพื่อแจ้ง "ความผิดปกติของข้อมูลประจำตัว" ที่อาจเกิดขึ้น

SELECT 
    s.target_id AS suspect_id,
    c.customer_email,
    s.similarity_score AS behavioral_overlap,
    c.community_id AS social_group
FROM CustomerSimilarity s
JOIN Customer c ON s.target_id = c.customer_id
WHERE s.customer_id = 'C1' -- Reference Alice (Legitimate)
  AND s.similarity_score > 0.15 
  AND c.community_id != 0 -- Filter for social strangers
ORDER BY s.similarity_score DESC;

รายงานการระบุความผิดปกติจะให้ข้อมูลที่สำคัญ การแยกผู้ใช้ที่ทำตัวเหมือนลูกค้าที่ถูกต้องแต่ไม่มีความเชื่อมโยงทางสังคมช่วยให้เราเปลี่ยนจากการคาดเดาไปสู่ความแน่นอนทางคณิตศาสตร์ได้

suspect_id

customer_email

behavioral_overlap

social_group

C10

judy@example.com

0.200000003

1

C9

ivan@example.com

0.200000003

1

การวิเคราะห์ผลลัพธ์

การรวม Similarity (Jaccard) เข้ากับ Community Detection (WCC) ทำให้เราเห็นความเสี่ยงที่ซ่อนอยู่ซึ่งข้อมูลธุรกรรมแบบดั้งเดิมมองไม่เห็น

  • "คู่แฝดเชิงพฤติกรรม" (ความใกล้เคียง): ระบบจะแจ้งว่าโหนดอย่าง Judy (C10) และ Ivan (C9) มีความคล้ายคลึงกันเนื่องจากมีคะแนนความคล้ายคลึงของ Jaccard เท่ากับ 0.20 เมื่อเทียบกับ Alice (C1)
  • ลักษณะการทำงานแบบแยก: ระบบจะจัดกลุ่ม Judy (C10) และ Ivan (C9) ไว้ใน community_id 1 ที่แยกไว้ ส่วน Alice จะอยู่ใน "Mainland" (ชุมชน 0) ซึ่งเป็นชุมชนโซเชียล
  • การแจ้งว่าเป็นการประพฤติมิชอบ: รายงานจะระบุผู้ใช้ที่มีการทับซ้อนกันของพฤติกรรมสูง (>0.9) ซึ่งยังคงไม่ได้เชื่อมต่อกับเครือข่ายหลัก

9. ขอแสดงความยินดีและสรุป

แล็บนี้แสดงให้เห็นว่า Cloud Spanner เปลี่ยนฐานข้อมูลเชิงสัมพันธ์ให้กลายเป็นเครื่องมือแบบหลายโมเดลได้อย่างไร การใช้ความสามารถของกราฟกับลูกค้าทำให้เราเปลี่ยนจากข้อมูลแบบคงที่ไปเป็นกลยุทธ์ทางธุรกิจที่นำไปใช้ได้จริง

ข้อดีของ Spanner Multi-Model

  • สถาปัตยกรรมแบบรวม: Spanner ช่วยให้คุณรักษาพื้นฐานเชิงสัมพันธ์ที่มั่นคงได้ในขณะที่ "ซ้อนทับ" กราฟพร็อพเพอร์ตี้เพื่อการค้นหาความสัมพันธ์ได้ทันทีโดยไม่ต้องเสี่ยงและหน่วงเวลา ETL
  • การแยกการวิเคราะห์นอกกล่อง: การใช้ประโยชน์จาก Data Boost ช่วยให้คุณเรียกใช้อัลกอริทึมที่ใช้หน่วยความจำสูง เช่น PageRank หรือ WCC ในทรัพยากรการคำนวณแบบไร้เซิร์ฟเวอร์ที่เป็นอิสระได้ ซึ่งจะช่วยให้มั่นใจได้ว่าจะไม่มีผลกระทบต่อประสิทธิภาพการชำระเงินในเวอร์ชันที่ใช้งานจริง
  • ประสิทธิภาพแบบ Interleaved: การ Interleaved ที่ไม่เหมือนใครของ Spanner ช่วยให้มั่นใจได้ว่าโหนดและความสัมพันธ์ของโหนดจะอยู่ร่วมกันทางกายภาพ ซึ่งจะเปลี่ยนการข้ามผ่านทั่วโลกที่ซับซ้อนเป็นการค้นหาในเครื่องที่มีความเร็วสูง

การแสดง "อัญมณีที่ซ่อนอยู่" และความผิดปกติ

  • การระบุคุณค่าเชิงโครงสร้าง: อัลกอริทึมกราฟ เช่น Betweenness Centrality เผยให้เห็น "สะพานที่ซ่อนอยู่" ซึ่งไม่มีการใช้จ่าย แต่อาจมีความสําคัญต่อความยืดหยุ่นของเครือข่ายมากกว่าลูกค้าที่ใช้จ่ายสูงสุด
  • การเปิดเผยการเลียนแบบพฤติกรรม: การรวมความคล้ายคลึงของ Jaccard และคอมโพเนนต์ที่เชื่อมต่ออย่างอ่อนทำให้เราระบุ "คนแปลกหน้าในโซเชียล" ได้ บัญชีเหล่านี้ดูเหมือนลูกค้าที่ถูกต้อง แต่ได้รับการพิสูจน์ทางคณิตศาสตร์แล้วว่าเป็นกลุ่มการประพฤติมิชอบที่แยกกัน
  • ความจริงระดับโลกเทียบกับระดับท้องถิ่น: แม้ว่าการวิเคราะห์ SQL ด้วยตนเองจะแสดงบริดจ์ได้ แต่อัลกอริทึมระดับโลกจะแสดงผู้ดูแลหลักของเครือข่ายได้

การทำให้ข้อมูลมีความอัจฉริยะและนำไปใช้ได้จริง

  • กลยุทธ์ที่อิงตามลักษณะตัวตน: เราเปลี่ยนแถวให้เป็นความสัมพันธ์ได้สำเร็จ และการเรียกใช้อัลกอริทึมช่วยให้เราแก้ปัญหาทางธุรกิจได้ 4 อย่าง ได้แก่ Network Bridges, Social Superstars, Fraud Risks และ Standard Users