結構定義總覽

本文說明屬性圖結構定義的元件,並介紹如何建立及管理圖表結構定義。

圖形可讓您模擬連線資料,以節點和邊緣網路的形式呈現資訊。圖形結構定義包含節點和邊緣,以及分類類型的標籤和描述這些節點和邊緣的屬性。您可以將輸入資料表中的資料列對應至圖形節點和邊緣,並定義自訂標籤和屬性,藉此定義屬性圖形結構定義。如要進一步瞭解 BigQuery 圖表,請參閱「BigQuery 圖表總覽」。

瞭解屬性圖資料模型

屬性圖形可讓您將連結的資料模擬為節點和邊緣的網路。節點代表資料中的實體,例如顧客、產品或位置。邊緣代表這些節點之間的連結,可擷取關係,例如購買、追蹤或位置。

節點和邊緣可能包含下列資訊:

  • 標籤:分類節點和邊緣類型。舉例來說,班級中的學生可能會有 Student 標籤和 Person 標籤。如果沒有明確定義節點或邊緣的標籤,BigQuery 圖形會使用輸入表格名稱做為預設標籤。

  • 屬性:用於描述節點和邊緣。舉例來說,代表人員的節點可能具有值為 Alexname 屬性,以及值為 1id 屬性。

圖 1 中的範例顯示如何設計圖表,模擬金融活動。這個圖表包含以下類型的實體 (以節點形式模擬):

  • 人員:代表參與金融交易的個人。
  • 帳戶:代表用於交易的銀行帳戶。

這些實體會透過不同類型的關係連結,並以以下有向邊表示:

  • 擁有:一個人擁有一或多個帳戶。
  • 轉移:將資金從一個帳戶轉移至另一個帳戶。

每個有向邊都表示從來源節點流向目的地節點的單向關係。舉例來說,Transfers 邊緣會將來源 Account 連接至目的地 Account,表示資金流向。

金融圖形的節點、邊緣、標籤和屬性。

圖 1. 含有多個節點和有向邊的圖表範例。

節點和邊緣包含屬性中的其他資訊。

  • Person 節點包含下列屬性:

    • name (STRING)
    • id (INT64)
  • Transfers 邊緣包含這個屬性:

    • amount (FLOAT64)

有向和無向邊

直接邊緣表示實體間關係的特定方向。舉例來說,使用者可以擁有帳戶,但帳戶無法擁有使用者。不過,有些關係 (例如社群網路中的好友關係) 是無向,代表互惠連結。在這種情況下,您可以將無向邊緣模擬為兩個有向邊緣,每個方向各一個邊緣。

設計結構定義

您可以使用 BigQuery 圖表,透過 CREATE PROPERTY GRAPH 陳述式從資料表建立圖表。建立圖表的資料表稱為「輸入資料表」

定義節點

節點是由資料表中的資料列定義。如要定義節點,請在 NODE TABLES 子句中加入節點定義。最簡單的節點定義形式包含輸入資料表的名稱和主鍵。BigQuery Graph 會將輸入資料表的資料列對應至圖形節點。

在下列範例中,您會使用 NODE TABLES 子句在 FinGraph 屬性圖中定義 Account 節點。節點定義包含輸入資料表 Account

-- Create an Account table.
CREATE TABLE graph_db.Account (
  id           INT64 NOT NULL,
  create_time  TIMESTAMP,
  PRIMARY KEY (id) NOT ENFORCED
);

-- Use the Account table as the input table for the Account node definition.
CREATE PROPERTY GRAPH graph_db.FinGraph
  NODE TABLES (
    graph_db.Account
  );

根據預設,BigQuery 會使用資料表名稱做為標籤,並將輸入資料表中的所有資料欄公開為屬性。

  • 每個帳戶節點都會使用 Account 標籤。
  • 每個帳戶節點都包含 Account 資料表欄中的 idcreate_time 屬性。

元素鍵

節點定義也會定義元素鍵,也就是一組可唯一識別圖形節點的資料欄。根據預設,元素鍵是輸入資料表的主鍵。您也可以使用 KEY 子句明確定義元素鍵。

以下範例會定義 Account 節點和 Person 節點。Account 節點會使用 Account 資料表的主鍵做為元素鍵。Person 節點會使用 KEY 子句,明確指定 id 資料欄做為元素鍵。

CREATE TABLE graph_db.Person (
  id           INT64 NOT NULL,
  name         STRING
);

CREATE TABLE graph_db.Account (
  id           INT64 NOT NULL,
  create_time  TIMESTAMP,
  PRIMARY KEY (id) NOT ENFORCED
);

CREATE PROPERTY GRAPH graph_db.FinGraph
  NODE TABLES (
    graph_db.Person KEY (id),
    graph_db.Account
  );
  • 凡是元素鍵不為空值的資料列,都會對應至圖形中由元素鍵識別的專屬節點。
  • 系統會忽略元素鍵為空值的資料列。

多個節點定義可使用相同的輸入資料表。在本例中,輸入資料表中的指定資料列會對應至每個節點定義的一個節點。

定義邊緣

邊緣是由資料表中的資料列定義。如要定義邊緣,請在 EDGE TABLES 子句中加入邊緣定義。最簡單的邊緣定義形式包含輸入資料表的名稱,並定義來源和目的地節點參照。BigQuery Graph 會使用這項定義,將輸入資料表中的資料列對應至圖形邊緣。

根據預設,BigQuery 會使用資料表名稱做為標籤,並將輸入資料表中的所有資料欄公開為屬性。

來源和目的地節點參照

邊緣定義會使用 SOURCE KEYDESTINATION KEYREFERENCES 子句,定義來源和目的地節點參照。您必須先定義來源和目的地節點,才能在邊緣定義中使用這些節點。

在下列範例中,您會建立具有下列項目的屬性圖 FinGraph

  • PersonAccount 節點
  • PersonOwnAccount edge
CREATE TABLE graph_db.Person (
  id            INT64 NOT NULL,
  name          STRING,
  PRIMARY KEY (id) NOT ENFORCED
);

CREATE TABLE graph_db.Account (
  id            INT64 NOT NULL,
  create_time   TIMESTAMP,
  PRIMARY KEY (id) NOT ENFORCED
);

CREATE TABLE graph_db.PersonOwnAccount (
  id            INT64 NOT NULL,
  account_id    INT64 NOT NULL,
  create_time   TIMESTAMP,
  FOREIGN KEY (account_id) REFERENCES graph_db.Account (id) NOT ENFORCED,
  PRIMARY KEY (id, account_id) NOT ENFORCED
);

CREATE PROPERTY GRAPH graph_db.FinGraph
  NODE TABLES (
    graph_db.Person,
    graph_db.Account
  )
  EDGE TABLES (
    PersonOwnAccount
      SOURCE KEY (id) REFERENCES Person (id)
      DESTINATION KEY (account_id) REFERENCES Account (id)
  );

每個 PersonOwnAccount 邊緣都會將 Person (來源) 節點連線至 Account (目的地) 節點。

  • 邊緣的來源節點是 Person 節點,其中 id 屬性與邊緣 id 屬性相同。
  • 邊緣的目的地節點是 Account 節點,其中 id 屬性與邊緣 account_id 屬性相同。
  • 元素鍵是 PersonOwnAccount 資料表的主鍵,也就是 (id, account_id)
  • 每個邊緣都有一組屬性,與 PersonOwnAccount 資料表中的資料欄相同。
  • 每個邊緣都有預設的 PersonOwnAccount 標籤。

將列對應至邊緣

邊緣輸入資料表中的每一列 (含非空元素鍵) 通常會對應至圖形中的單一邊緣。不過,如果來源或目的地節點參照與來源或目的地節點資料表中的零或多個節點相符,邊緣輸入資料表中的資料列可能會在圖形中產生零或多個邊緣。

在單一資料表中定義節點和邊緣

如果資料表的資料欄定義與其他資料表的關係,您可以在單一資料表中定義節點及其傳入或傳出的邊。這種做法可減少資料表數量、簡化資料管理,並消除聯結至個別邊緣資料表的需求,進而提升查詢效能。

舉例來說,如果下列 Account 資料表具有複合主鍵 (owner_id, account_id),則 owner_id 資料欄可以是參照 Person 資料表的外鍵。這種結構可讓 Account 資料表同時代表 Account 節點和來自 Person 節點的傳入邊緣。

CREATE TABLE graph_db.Person (
  id INT64 NOT NULL,
  PRIMARY KEY (id) NOT ENFORCED
);

-- Assume each account has exactly one owner.
CREATE TABLE graph_db.Account (
  owner_id INT64 NOT NULL,
  account_id INT64 NOT NULL,
  FOREIGN KEY (owner_id) REFERENCES graph_db.Person(id) NOT ENFORCED,
  PRIMARY KEY (owner_id, account_id) NOT ENFORCED
);

您可以使用 Account 資料表定義 Account 節點及其傳入的 Owns 邊緣。這會在下列 CREATE PROPERTY GRAPH 陳述式中顯示。在 EDGE TABLES 子句中,您會為 Account 資料表提供別名 Owns。這是因為圖表結構定義中的每個元素都必須有專屬名稱。

CREATE PROPERTY GRAPH graph_db.FinGraph
  NODE TABLES (
    graph_db.Person,
    graph_db.Account
  )
  EDGE TABLES (
    graph_db.Account AS Owns
      SOURCE KEY (owner_id) REFERENCES Person
      DESTINATION KEY (owner_id, account_id) REFERENCES Account
  );

自訂標籤和屬性

您可以使用 LABELPROPERTIES 子句自訂標籤和屬性。

以下範例會定義具有自訂屬性的 Person 節點,以及具有多個標籤的 Account 節點:

CREATE TABLE graph_db.Person (
  id               INT64 NOT NULL,
  name             STRING,
  birthday         TIMESTAMP,
  country          STRING,
  city             STRING,
  PRIMARY KEY (id) NOT ENFORCED
);

CREATE TABLE graph_db.Account (
  id               INT64 NOT NULL,
  create_time      TIMESTAMP,
  is_blocked       BOOL,
  nick_name        STRING,
  PRIMARY KEY (id) NOT ENFORCED
);

CREATE PROPERTY GRAPH graph_db.FinGraph
  NODE TABLES (
    graph_db.Person KEY (id)
      LABEL Customer
      PROPERTIES (CONCAT(city, ", ", country) AS address)
      LABEL Entity PROPERTIES (id, name),
    graph_db.Account KEY (id)
      DEFAULT LABEL OPTIONS(description = 'A checking or savings account')
      PROPERTIES (id, create_time)
      LABEL Entity
      PROPERTIES (
        id,
        nick_name AS name OPTIONS(description = 'A user-defined account name',
                                  synonyms = ['friendly name', 'display name'])
      )
  );
  • Person 節點會使用 Customer 標籤公開 address 屬性。address 屬性是由參照輸入資料表 Personcitycountry 資料欄的運算式 CONCAT(city, ", ", country), 定義。

  • Account 節點會使用 Account 標籤公開 idcreate_time 屬性。

PersonAccount 節點都有 Entity 標籤,以及 idname 屬性。

  • Person 節點中,idname 屬性來自輸入表格資料欄。
  • Account 節點中,name 屬性是指輸入資料表的 nick_name 資料欄。
  • Account 節點中,name 屬性會使用 OPTIONS 子句提供屬性說明和同義字清單。這些欄位可提供脈絡資訊,並提升自然語言查詢介面的曝光度。您無法在圖形查詢中直接存取這些欄位,且這些欄位不會以任何方式變更查詢結果。

標籤和屬性一致性

在圖表中,標籤和屬性會以名稱做為專屬 ID。您可以在多個節點或邊緣定義中使用同名的標籤和屬性。不過,名稱相同的標籤和屬性必須遵守下列規則:

  • 名稱相同的屬性必須使用相同的值類型。
  • 名稱相同的標籤必須公開相同的屬性清單。

在前例中,PersonAccount 節點都定義了 Entity 標籤。兩個定義都包含相同的屬性名稱集 (idname),且值類型相同。

管理結構定義依附元件

圖表取決於節點和邊緣定義的輸入資料表結構定義,以及屬性參照的資料表資料欄。BigQuery 圖表不會檢查刪除或變更資料表或資料欄是否會導致現有圖表結構定義失效。

您有責任避免破壞結構定義的變更。請遵循下列最佳做法:

  • 如要刪除圖表節點定義中使用的資料表,請先從圖表中移除該節點定義。
  • 從圖表中以屬性形式公開的資料表移除資料欄前,請先從對應的節點或邊緣定義中移除該屬性。

查看圖表結構定義

如要查看用於建構現有圖表的 CREATE PROPERTY GRAPH 陳述式,請查詢 INFORMATION_SCHEMA.PROPERTY_GRAPHS 檢視區塊

SELECT
  property_graph_name,
  ddl
FROM
  `region-REGION`.INFORMATION_SCHEMA.PROPERTY_GRAPHS;

REGION 替換為包含圖表的資料集區域。

或者,您也可以在筆記本中以視覺化方式呈現圖表結構定義

更新圖表結構定義

如要變更現有圖表的結構定義,必須使用 CREATE PROPERTY GRAPH 陳述式重新定義圖表結構定義。

刪除圖表結構定義

如要刪除屬性圖,請使用 DROP PROPERTY GRAPH 陳述式

最佳做法

以下各節說明定義圖表結構定義的最佳做法,有助於提升圖表查詢效能。

設定資源定義的範圍

屬性是鍵值組,可提供附加至節點或邊緣的其他資訊。建議您只在節點或邊緣中加入必要屬性,並避免使用 PROPERTIES ALL COLUMNS 語法或預設語法,將節點或邊緣資料表的所有資料欄附加至屬性清單。節點或邊緣中若有許多屬性,可能會導致圖形查詢中出現不必要的資料欄掃描,進而降低效能。

如要限制節點或邊緣定義中包含的屬性,請在 CREATE PROPERTY GRAPH 陳述式中定義元素屬性時,使用 PROPERTIES 關鍵字。

下列節點資料表定義會將 Person 節點資料表的屬性限制為 idname

NODE TABLES (
  graph_db.Person PROPERTIES (id, name)
)

在圖形節點和邊緣上定義主鍵和外鍵限制

BigQuery 可在節點和邊緣資料表上使用主鍵和外鍵限制,減少不必要的資料表掃描,進而最佳化圖形查詢。不過,BigQuery 不會強制執行資料表的主鍵或外鍵限制。如果應用程式無法保證參照完整性或主鍵的唯一性,使用主鍵或外鍵進行查詢最佳化可能會導致查詢結果不正確。

下列範例會在節點資料表 PersonAccount,以及邊緣資料表 PersonOwnAccount 上定義主鍵和外鍵限制:

CREATE OR REPLACE TABLE graph_db.Person (
  id               INT64,
  name             STRING,
  birthday         TIMESTAMP,
  country          STRING,
  city             STRING,
  PRIMARY KEY (id) NOT ENFORCED
);

CREATE OR REPLACE TABLE graph_db.Account (
  id               INT64,
  create_time      TIMESTAMP,
  is_blocked       BOOL,
  nick_name        STRING,
  PRIMARY KEY (id) NOT ENFORCED
);

CREATE OR REPLACE TABLE graph_db.PersonOwnAccount (
  id               INT64 NOT NULL,
  account_id       INT64 NOT NULL,
  create_time      TIMESTAMP,
  PRIMARY KEY (id, account_id) NOT ENFORCED,
  FOREIGN KEY (id) references graph_db.Person(id) NOT ENFORCED,
  FOREIGN KEY (account_id) references graph_db.Account(id) NOT ENFORCED
);

後續步驟