SQL ビューを使用してグラフを作成する方法を学習します。このドキュメントでは、ビューを定義し、それらを使用してノードテーブルとエッジテーブルを定義する手順ガイドとコード例について説明します。ビューを使用してグラフを作成するユースケースを示すサンプルコードを含む例を確認する。ビューを使用してプロパティ グラフを作成する方法(メリットや考慮事項など)については、SQL ビューから作成されたグラフの概要をご覧ください。
始める前に
グラフを作成するには、次の操作を行います。
Spanner Graph 環境が設定されていることを確認します。
Spanner Graph スキーマの仕組みを理解する。
ビューを使用してグラフを作成する
ビューを使用してグラフを作成するには:
グラフのビューを定義します。デフォルトでは、要素の一意性を確保するために、ビューはサポートされているビューパターンのいずれかに従う必要があります。ビューでこれらのパターンに従わないクエリを使用している場合は、ステップ 4 でキーの一意性の検証を無効にできます。詳細については、ビューを作成するをご覧ください。
CREATE PROPERTY GRAPHステートメントのNODE TABLES句とEDGE TABLES句でビューを使用して、グラフを作成します。CREATE PROPERTY GRAPHステートメントにKEY句を含めます。KEY句では、各グラフ要素を一意に識別するソースビューの列を指定します。省略可: ビューで、サポートされている一意性パターンに従わない任意の SQL クエリを使用する場合は、
CREATE PROPERTY GRAPHステートメントにOPTIONS (validate_element_key_uniqueness = false)句を追加します。KEY句の列が、ノードまたはエッジの行ごとに一意の値を生成するようにします。CREATE PROPERTY GRAPH MyGraph NODE TABLES ( CustomerViewTrusted KEY(id) ) OPTIONS (validate_element_key_uniqueness = false);詳細については、無効な鍵の検証(任意の SQL クエリ)をご覧ください。
省略可: ビューがリモート関数を呼び出す場合、または他の揮発性列がある場合は、
CREATE PROPERTY GRAPHステートメントにOPTIONS (allow_view_with_volatile_column = true)句を追加します。CREATE PROPERTY GRAPH MyGraph NODE TABLES ( AccountRemoteUdfView KEY(account_id) ) OPTIONS (allow_view_with_volatile_column = true);詳細については、ビューでリモート関数を使用するときに揮発性列を有効にするをご覧ください。
例: ビューを使用してグラフを作成する
この例では、Customer テーブルと Account テーブルに AsiaCustomer、AsiaBankAccount、AsiaAccountsOwnership のビューを作成します。次に、この例では、これらのビューを使用してグラフに次のものを作成します。
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_uniqueness が false に設定されていない限り、グラフ要素の作成に使用されるビューは、サポートされているパターンに従って、ビュー内の行が一意になるようにする必要があります。
-- 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 して、1 つの行から複数のエッジ関係をモデル化できます。
次のサプライ チェーン スキーマの例では、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)
);
リモート関数を使用してプロパティを計算する
ビューでリモート関数を使用して、CREATE
PROPERTY GRAPH ステートメントの OPTIONS 句で allow_view_with_volatile_column = true を設定することで、グラフ要素の派生プロパティを計算することもできます。詳細については、ビューでリモート関数を使用する場合に揮発性列を有効にするをご覧ください。
-- Define a remote function.
CREATE FUNCTION rudf_identity_func(x INT64)
RETURNS INT64 NOT DETERMINISTIC LANGUAGE REMOTE
OPTIONS (
endpoint = 'https://us-central1-project-id.cloudfunctions.net/my-func'
);
-- Base table for accounts.
CREATE TABLE Account (
account_id INT64 NOT NULL,
balance INT64
) PRIMARY KEY (account_id);
-- View that computes a property using the remote function.
CREATE VIEW AccountRemoteUdfView SQL SECURITY INVOKER AS
SELECT
t.account_id,
t.balance,
rudf_identity_func(t.account_id) AS view_computed_prop
FROM Account AS t;
-- Graph using the view requires allow_view_with_volatile_column = true.
CREATE PROPERTY GRAPH AccountViewRemoteUdfGraph
NODE TABLES (
AccountRemoteUdfView KEY (account_id)
PROPERTIES (account_id, balance, view_computed_prop)
)
OPTIONS (allow_view_with_volatile_column = true);
例: スキーマレス データ移行
スキーマレス データ マネジメントでは、事前定義されたノードタイプとエッジタイプを使用せずに、柔軟なグラフ定義を作成できます。スキーマレス データ マネジメントは柔軟性を提供しますが、データがより明確に定義されるにつれて、より正式な構造に移行する必要が生じることがあります。より正式な構造では、グラフのノードとエッジの関係、ラベル、プロパティがスキーマに公開されるため、グラフスキーマを理解するために手動でデータを探索する必要性が軽減されます。
ビューを使用すると、基盤となるデータを移行せずに、ノードタイプとエッジタイプを形式化できます。たとえば、正規の GraphNode テーブルと GraphEdge テーブルを使用する一般的なスキーマレス モデルから移行できます。これを行うには、スキーマレス テーブルからデータを抽出するビューを作成します。
形式化するノードとエッジのタイプ(
PersonやWorksForなど)ごとにビューを定義します。ビューで、ラベル(WHERE n_label = "person"など)でデータをフィルタし、JSON 列のプロパティを特定のデータ型(STRING(prop.name) AS nameなど)にキャストします。NODE TABLESとEDGE TABLESが、作成した型付きビューを参照する新しいプロパティ グラフを定義します。
スキーマレス グラフは、一部のクエリ(複数のエッジタイプを持つ定量化されたパスパターンなど)で、形式化されたグラフよりもパフォーマンスが向上します。ユースケースで正式なメタデータが重要な場合は、ビューを使用してスキーマレス グラフから型付きスキーマに移行できます。また、一部のユースケースではスキーマレス グラフを使用し、他のユースケースでは型付きスキーマ グラフを使用することもできます。詳細については、グラフクエリに基づいてスキーマ設計を選択するをご覧ください。
次の例は、スキーマレス グラフから正式なグラフに移行するワークフローを 4 つのステップで示しています。
スキーマレス モデルの正規の
GraphNodeテーブルとGraphEdgeテーブルを定義します。これらのスキーマレス テーブルに、初期の柔軟なグラフを作成します。
スキーマレス テーブルからデータを抽出して正規化する型付きビュー(
Person、Company、WorksFor)を定義します。これらのビューをノードテーブルとエッジテーブルとして使用する、最終的な強く型付けされたグラフを作成します。
-- 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)
);
次のステップ
詳しくは、要素キーの一意性の要件をご覧ください。
Spanner Graph のスキーマについて学習する。