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

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

始める前に

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

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

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

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

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

  1. グラフのビューを定義します。デフォルトでは、要素の一意性を確保するために、ビューは サポートされているビュー パターン のいずれかに従う必要があります。ビューでこれらのパターンに従わないクエリを使用する場合は、ステップ 4 でキーの一意性検証を無効にできます。詳細については、ビューを作成するをご覧ください。

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

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

  4. 省略可: ビューで、サポートされている一意性パターンに従わない任意の SQL クエリを使用する場合は、OPTIONS (validate_element_key_uniqueness = false) 句を CREATE PROPERTY GRAPH ステートメントに追加します。KEY 句の列が、すべてのノードまたはエッジの行に対して一意の値を生成することを確認します。

    CREATE PROPERTY GRAPH MyGraph
      NODE TABLES (
        CustomerViewTrusted KEY(id)
      ) OPTIONS (validate_element_key_uniqueness = false);
    

    詳細については、 キー検証の無効化(任意の SQL クエリ)をご覧ください。

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

この例では、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: ビューを作成する

次に、テーブルからデータを変換またはフィルタするビューを作成します。これらのビューは、アジアの顧客とアカウントのみを含めるようにテーブルをフィルタします。 validate_element_key_uniquenessfalse に設定されていない限り、グラフ 要素の作成に使用されるビューは、ビュー内の行が一意であることを保証するために、サポートされているパターンに従う必要があります

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

次のステップ