SQL ビューを使用してグラフを作成する方法について説明します。このドキュメントでは、ビューを定義し、それを使用してノードテーブルとエッジテーブルを定義する手順とコードサンプルについて説明します。ビューを使用してグラフを作成するユースケースを示すサンプルコードを含む例をご覧ください。ビューを使用してプロパティ グラフを作成する方法(メリットや考慮事項など)については、SQL ビューから作成されたグラフの概要をご覧ください。
始める前に
グラフを作成するには、次の操作を行う必要があります。
Spanner Graph 環境が設定されていることを確認します。
Spanner Graph スキーマの仕組みを理解する。
ビューを使用してグラフを作成する
ビューを使用してグラフを作成するには:
グラフのビューを定義します。ビューが必要なビュー パターンのいずれかに準拠していることを確認します。詳細については、ビューを作成するをご覧ください。
CREATE PROPERTY GRAPHステートメントのNODE TABLES句とEDGE TABLES句でビューを使用して、グラフを作成します。CREATE PROPERTY GRAPHステートメントにKEY句を含めます。KEY句では、各グラフ要素を一意に識別するソースビューの列を指定します。
例: ビューを使用してグラフを作成する
この例では、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: ビューを作成する
次に、テーブルからデータを変換またはフィルタするビューを作成します。これらのビューは、アジアの顧客とアカウントのみを含むようにテーブルをフィルタします。グラフ要素の作成に使用されるビューでは、ビュー内の行が一意であることを確認する必要があります。
-- 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 テーブルを使用する一般的なスキーマレス モデルから移行できます。これを行うには、スキーマレス テーブルからデータを抽出するビューを作成します。
形式化するノードタイプとエッジタイプ(
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 のスキーマについて学習する。