SQL ビューからグラフを作成する

SQL ビューを使用してグラフを作成する方法について説明します。このドキュメントでは、ビューを定義し、それを使用してノードテーブルとエッジテーブルを定義する手順とコードサンプルについて説明します。ビューを使用してグラフを作成するユースケースを示すサンプルコードを含むをご覧ください。ビューを使用してプロパティ グラフを作成する方法(メリットや考慮事項など)については、SQL ビューから作成されたグラフの概要をご覧ください。

始める前に

グラフを作成するには、次の操作を行う必要があります。

  1. Spanner Graph 環境が設定されていることを確認します。

  2. Spanner Graph スキーマの仕組みを理解する。

ビューを使用してグラフを作成する

ビューを使用してグラフを作成するには:

  1. グラフのビューを定義します。ビューが必要なビュー パターンのいずれかに準拠していることを確認します。詳細については、ビューを作成するをご覧ください。

  2. CREATE PROPERTY GRAPH ステートメントの NODE TABLES 句と EDGE TABLES 句でビューを使用して、グラフを作成します。

  3. CREATE PROPERTY GRAPH ステートメントに KEY 句を含めます。KEY 句では、各グラフ要素を一意に識別するソースビューの列を指定します。

例: ビューを使用してグラフを作成する

この例では、Customer テーブルと Account テーブルに対して AsiaCustomerAsiaBankAccountAsiaAccountsOwnership のビューを作成します。次に、この例では、これらのビューを使用してグラフに次のものを作成します。

  • AsiaCustomer ビューを使用して Customer ノードテーブルを作成します。

  • AsiaBankAccount ビューを使用して Account ノードテーブルを作成します。

  • AsiaAccountsOwnership ビューを使用して Owns エッジテーブルを作成します。このエッジは、Customer ノードと Account ノードを接続します。

ステップ 1: テーブルを作成する

まず、データテーブルを作成します。次のコードは、Customer テーブルと Account テーブルを作成します。

CREATE TABLE Customer (
  customer_id INT64 NOT NULL,
  name STRING(MAX),
  address_continent STRING(MAX),
  address_country STRING(MAX),
) PRIMARY KEY(customer_id);

CREATE TABLE Account (
  account_id INT64 NOT NULL,
  customer_id INT64 NOT NULL,
  account_type STRING(MAX),
  balance INT64,
  create_time TIMESTAMP,
  address_continent STRING(MAX),
  address_country STRING(MAX),
  CONSTRAINT FK_CustomerId FOREIGN KEY (customer_id)
    REFERENCES Customer (customer_id)
) PRIMARY KEY(account_id);

ステップ 2: ビューを作成する

次に、テーブルからデータを変換またはフィルタするビューを作成します。これらのビューは、アジアの顧客とアカウントのみを含むようにテーブルをフィルタします。グラフ要素の作成に使用されるビューでは、ビュー内の行が一意であることを確認する必要があります。

-- View for 'Customer' nodes, filtered for Asia
CREATE VIEW AsiaCustomer
  SQL SECURITY INVOKER AS
    SELECT customer.customer_id, customer.name
    FROM Customer customer
    WHERE LOWER(customer.address_continent) = "asia";

-- View for 'Account' nodes, filtered for Asia.
CREATE VIEW AsiaBankAccount
  SQL SECURITY INVOKER AS
    SELECT account.account_id, account.balance, account.account_type, account.create_time
    FROM Account account
    WHERE LOWER(account.address_continent) = "asia";

-- View for 'Owns' edges, connecting customers to accounts in Asia.
CREATE VIEW AsiaAccountsOwnership
  SQL SECURITY INVOKER AS
    SELECT account.customer_id, account.account_id
    FROM Account account
    WHERE LOWER(account.address_continent) = "asia";

ステップ 3: プロパティ グラフを作成する

次に、作成したビューを使用して AsiaFinGraph を作成します。CREATE PROPERTY GRAPH ステートメントには、グラフ要素を一意に識別する列を指定する各グラフ要素定義の KEY 句が含まれています。

CREATE PROPERTY GRAPH AsiaFinGraph
  NODE TABLES (
    AsiaCustomer AS Customer KEY(customer_id),
    AsiaBankAccount AS Account KEY(account_id)
  )
  EDGE TABLES (
    AsiaAccountsOwnership AS Owns
      KEY(customer_id, account_id)
      SOURCE KEY (customer_id) REFERENCES Customer (customer_id)
      DESTINATION KEY (account_id) REFERENCES Account (account_id)
  );

ユースケースの例

SQL ビューには、プロパティ グラフ要素にテーブルを使用するよりもメリットがあります。次の例は、テーブルではなくビューを使用してグラフ要素を定義するユースケースを示しています。

例: きめ細かいグラフデータ アクセス制御を適用する

グラフデータにきめ細かいセキュリティを適用するには、定義者の権限ビューを使用してノードテーブルまたはエッジテーブルを定義します。ビューは、基盤となるデータの許可されたサブセットをグラフに公開します。

たとえば、グラフへのアクセスをエンジニアリング費用センターの従業員のみに制限するには、EngineerEmployeeView ビューを作成し、GRANT 句を使用して、ビューに対する SELECT 権限を engineering_data_reader ロールに付与します。

このビューを使用してグラフノード テーブルを定義すると、engineering_data_reader ロールでグラフクエリを実行するユーザーには、ビューでフィルタされた行(エンジニアリング部門の従業員を含む)のみが表示されます。

-- The table containing all employee data.
CREATE TABLE Employee (
  id INT64 NOT NULL,
  cost_center STRING(MAX),
  job_title STRING(MAX),
  office STRING(MAX)
) PRIMARY KEY (id);

-- The definer's rights view that filters for engineering employees.
CREATE VIEW EngineerEmployeeView SQL SECURITY DEFINER AS
  SELECT e.id, e.cost_center, e.job_title, e.office
  FROM Employee e
  WHERE LOWER(e.cost_center) = "engineering";

-- The role that is granted to read the view.
CREATE ROLE engineering_data_reader;
GRANT SELECT ON VIEW EngineerEmployeeView TO ROLE engineering_data_reader;

-- The graph that uses definer's rights view.
CREATE PROPERTY GRAPH EngineeringGraph
  NODE TABLES (
    EngineerEmployeeView KEY(id)
  );

例: モデルから派生したグラフ要素

ビューを使用すると、データ変換が必要なグラフ要素を定義できます。主なメリットは、ビューで変換が定義されるため、派生データのテーブルを別途維持する必要がないことです。

たとえば、ARRAY 列(または JSON 列内の配列フィールド)から UNNEST データを取得して、単一行から複数のエッジ関係をモデル化できます。

次のサプライ チェーン スキーマの例では、Parts テーブルに dependent_parts 配列でサブコンポーネントのリストが格納されています。ビューは UNNEST 演算子を使用して、配列の各要素を個別の行に変換できます。このビューはエッジテーブルとして機能し、PartDependsOnPart エッジをモデル化してパーツ間の依存関係を表すことができます。

-- Parts table with an ARRAY of dependent parts.
CREATE TABLE Parts (
  part_id INT64 NOT NULL,
  dependent_parts ARRAY<INT64>
) PRIMARY KEY (part_id);

-- A view that unnests the dependent_parts array.
-- GROUP BY ensures uniqueness for the graph element KEY.
CREATE VIEW PartDependsOnPart SQL SECURITY INVOKER AS
  SELECT p.part_id, dependent_part_id
  FROM Parts AS p,
    UNNEST(p.dependent_parts) AS dependent_part_id
  GROUP BY p.part_id, dependent_part_id;

-- Graph modeling the part dependency relationship.
CREATE PROPERTY GRAPH SupplyChainGraph
  NODE TABLES (
    Parts
  )
  EDGE TABLES (
    PartDependsOnPart KEY (part_id, dependent_part_id)
      SOURCE KEY (part_id) REFERENCES Parts(part_id)
      DESTINATION KEY (dependent_part_id) REFERENCES Parts(part_id)
  );

例: スキーマレスなデータ移行

スキーマレス データ管理では、事前定義されたノードとエッジの型を使用せずに、柔軟なグラフ定義を作成できます。スキーマレス データ管理は柔軟性を提供しますが、データがより明確になるにつれて、より正式な構造に移行する必要が生じる可能性があります。より正式な構造では、グラフのノードとエッジの関係、ラベル、プロパティがスキーマで公開されるため、グラフ スキーマを理解するために手動でデータを探索する必要がなくなります。

ビューを使用すると、基盤となるデータを移行せずにノードとエッジのタイプを形式化できます。たとえば、正規の GraphNode テーブルと GraphEdge テーブルを使用する一般的なスキーマレス モデルから移行できます。これを行うには、スキーマレス テーブルからデータを抽出するビューを作成します。

  1. 形式化するノードタイプとエッジタイプ(PersonWorksFor など)ごとにビューを定義します。ビューで、ラベル(WHERE n_label = "person" など)でデータをフィルタし、JSON 列のプロパティを特定のデータ型(STRING(prop.name) AS name など)にキャストします。

  2. NODE TABLESEDGE TABLES が、作成した型付きビューを参照する新しいプロパティ グラフを定義します。

スキーマレス グラフは、一部のクエリ(複数のエッジタイプを含む定量化されたパスパターンなど)で、形式化されたグラフよりもパフォーマンスが向上します。ユースケースで形式化されたメタデータが重要な場合は、ビューを使用してスキーマレス グラフから型付きスキーマに移行できます。一部のユースケースではスキーマレス グラフを使用し、他のユースケースでは型付きスキーマ グラフを使用することもできます。詳細については、グラフクエリに基づいてスキーマ設計を選択するをご覧ください。

次の例は、スキーマレス グラフから形式化されたグラフに移行するワークフローを 4 つのステップで示しています。

  1. スキーマレス モデルの正規の GraphNode テーブルと GraphEdge テーブルを定義します。

  2. これらのスキーマレス テーブルに初期の柔軟なグラフを作成します。

  3. スキーマレス テーブルからデータを抽出して形式化する型付きビュー(PersonCompanyWorksFor)を定義します。

  4. これらのビューをノードテーブルとエッジテーブルとして使用する、最終的な厳密に型指定されたグラフを作成します。

-- 1. Create the canonical tables for a schemaless model.
CREATE TABLE GraphNode (
  id INT64 NOT NULL,
  label STRING(MAX) NOT NULL,
  properties JSON
) PRIMARY KEY (id);

CREATE TABLE GraphEdge (
  id INT64 NOT NULL,
  dest_id INT64 NOT NULL,
  edge_id INT64 NOT NULL,
  label STRING(MAX) NOT NULL,
  properties JSON
) PRIMARY KEY (id, dest_id, edge_id),
  INTERLEAVE IN PARENT GraphNode;

-- 2. Define a schemaless graph.
CREATE PROPERTY GRAPH FinGraph
  NODE TABLES (
    GraphNode
      DYNAMIC LABEL (label)
      DYNAMIC PROPERTIES (properties)
  )
  EDGE TABLES (
    GraphEdge
      SOURCE KEY (id) REFERENCES GraphNode(id)
      DESTINATION KEY (dest_id) REFERENCES GraphNode(id)
      DYNAMIC LABEL (label)
      DYNAMIC PROPERTIES (properties)
  );

-- 3. Define typed views that extract and formalize the data.
--    Convert JSON fields to primitive types (for example, INT64, STRING) to
--    ensure type safety.
CREATE VIEW Person SQL SECURITY INVOKER AS
  SELECT n.id, STRING(n.properties.name) AS name, INT64(n.properties.age) AS age
  FROM GraphNode n WHERE n.label = "person";

CREATE VIEW Company SQL SECURITY INVOKER AS
  SELECT n.id, STRING(n.properties.name) AS company_name, BOOL(n.properties.is_public) AS is_public
  FROM GraphNode n WHERE n.label = "company";

CREATE VIEW WorksFor SQL SECURITY INVOKER AS
  SELECT e.id AS person_id, e.dest_id AS company_id, e.edge_id AS edge_id, STRING(e.properties.since) AS since
  FROM GraphEdge e
  WHERE e.label = "worksfor";

-- 4. Create the final, formalized graph from the typed views.
CREATE PROPERTY GRAPH typed_formalized_graph
  NODE TABLES (
    Person KEY(id)
      PROPERTIES (name, age),
    Company KEY(id)
      PROPERTIES (company_name, is_public)
  )
  EDGE TABLES(
    WorksFor KEY(person_id, company_id, edge_id)
      SOURCE KEY (person_id) REFERENCES Person(id)
      DESTINATION KEY (company_id) REFERENCES Company(id)
      PROPERTIES (since)
  );

次のステップ