AnalyticDB for PostgreSQL は、age 拡張を通じてグラフ分析をサポートしており、これにより Cypher クエリ言語を PostgreSQL インスタンスで利用できます。このページでは、Cypher の動作原理を説明し、グラフの作成、データの書き込み、CRUD 操作の実行方法を順を追って解説します。
前提条件
作業を開始する前に、以下の要件を満たしていることを確認してください。
AnalyticDB for PostgreSQL V7.0 インスタンスで、マイナーエンジンバージョン V7.2.1.0 以降が実行されている必要があります。確認するには、AnalyticDB for PostgreSQL コンソールで [基本情報] ページを開きます。バージョンが古すぎる場合は、マイナーエンジンバージョンをアップデートする。
age拡張がインストールされていること。マイナーエンジンバージョン 7.2.1.4 以降を実行しているインスタンスでは、この拡張は自動的にインストールされます。それより古いバージョンの場合は、手動で拡張をインストールしてください。ag_catalogがsearch_pathに追加されていること。以下のいずれかを実行してください。セッションレベル(現在のセッションのみ):
SET search_path TO "$user", public, ag_catalog;データベースレベル(永続的):
ALTER DATABASE <database_name> SET search_path TO "$user", public, ag_catalog;
(オプション)他のユーザーが
ag_catalogスキーマにアクセスする必要がある場合、初期アカウント または RDS_SUPERUSER 権限を持つ特権アカウント を使用して権限を付与します。GRANT USAGE ON SCHEMA ag_catalog TO <username>;
基本概念
Cypher とは
Cypher は openCypher プロジェクトから提供されるオープンソースの宣言型グラフクエリ言語です。ノードを丸括弧、関係を角括弧、方向を矢印で表現する視覚的かつパターンベースの構文を採用しており、グラフの構造を直感的に反映します。そのため、SQL に慣れている開発者にとっても理解しやすい設計となっています。
MATCH (n:nodes)-[r:ARE_CONNECTED_TO]->(o:otherNodes)
RETURN n, r, oこのパターンでは、(n:nodes) はラベル nodes を持つノード(エイリアス:n)、[r:ARE_CONNECTED_TO] はタイプ ARE_CONNECTED_TO の有向関係(エイリアス:r)、(o:otherNodes) はラベル otherNodes を持つターゲットノード(エイリアス:o)を表します。このクエリは、このパターンに一致するすべてのソースノード、ターゲットノード、およびそれらを結ぶ関係を返します。
ノード構文
ノードは丸括弧 () で表現されます。
| 構文 | 説明 |
|---|---|
() | 匿名ノード — 任意のノードに一致 |
(node) | クエリ内で使用可能な変数 node を持つノード |
(:City) | City ラベルでフィルターされたノード |
(city:City) | 変数 city およびラベル City |
(city:City {name: 'Hangzhou'}) | プロパティによるフィルター — WHERE 句と同等 |
(city:City {name: 'Hangzhou', province: 'Zhejiang'}) | 複数のプロパティによるフィルター |
関係構文
関係はハイフン -- で表現されます。変数、タイプ、またはプロパティを含めるには角括弧 [] を追加します。方向を指定するには > を使用します。
| 構文 | 説明 |
|---|---|
-- | 匿名、無向リレーションシップ |
--> | 匿名、有向リレーションシップ |
-[role]-> | 変数 role |
-[:ACTED_IN]-> | 型 ACTED_IN |
-[role:ACTED_IN]-> | 変数と型を持つ有向リレーションシップ |
-[role:ACTED_IN {roles: ['Neo']}]-> | 変数、型、およびプロパティを持つ有向リレーションシップ |
パターン構文
ノード構文と関係構文を組み合わせて、豊かなグラフパターンを表現できます。例:
(city_from:City {province: 'Zhejiang'})-[:NEXT_TO]-(city_next:City {province: 'Jiangsu'})このパターンは、浙江省にある都市と江蘇省にある都市のペアで、無向の NEXT_TO 関係で接続されているものを一致させます。
サンプルグラフ
このページのすべての例では、以下のグラフを使用します。このグラフには、3つの Person ノード(Zhang San、Li Si、Wang Wu)と2つの Company ノード(Company A、Company C)が含まれています。人物は EMPLOYED エッジで会社に接続されており、人物同士は FRIENDS エッジおよび TEACHER エッジで接続されています。
以下のコマンドを実行して、グラフを作成し、サンプルデータをロードします。
次のセクションでは、このグラフ内のデータを照会、更新、削除する方法を示します。
グラフの作成
create_graph 関数を使用して新しいグラフを作成します。
SELECT create_graph('<graph_name>');<graph_name> は、グラフの名前に置き換えてください。
データの書き込み
すべての Cypher 書き込み操作は、ag_catalog 内の cypher 関数を経由して実行されます。cypher 呼び出し内に CREATE 文を使用して、ノードおよび関係を追加します。
SELECT * FROM cypher('<graph_name>', $$
/* Write a Cypher expression. */
$$) AS (result_a agtype);cypher 関数は結果を agtype として返します。返された各行には、一致した頂点またはエッジが、::vertex または ::edge で注釈された JSON 類似オブジェクトとして含まれます。
データの照会
MATCH および RETURN を使用してグラフデータを照会します。MATCH は検索するグラフパターンを指定し、RETURN は結果に含める内容を指定します。一致結果をフィルターするには、WHERE 句を追加します。
SELECT * FROM cypher('<graph_name>', $$
MATCH <pattern>
WHERE <condition> -- optional
RETURN <variables>
$$) AS (result_a agtype);すべてのノードまたはエッジの照会
Person ラベルを持つすべてのノードを検索します。
SELECT * FROM cypher('relation', $$
MATCH (m:Person)
RETURN m
$$) AS (result_a agtype);結果:
| result_a |
|---|
{"id": 844424930131969, "label": "Person", "properties": {"name": "Zhang San"}}::vertex |
{"id": 844424930131970, "label": "Person", "properties": {"name": "Li Si"}}::vertex |
{"id": 844424930131971, "label": "Person", "properties": {"name": "Wang Wu"}}::vertex |
EMPLOYED ラベルを持つすべてのエッジを検索します。
SELECT * FROM cypher('relation', $$
MATCH (:Person)-[r:EMPLOYED]->(:Company)
RETURN r
$$) AS (result_a agtype);結果:
| result_a |
|---|
{"id": 1407374883553281, "label": "EMPLOYED", "end_id": 1125899906842625, "start_id": 844424930131969, "properties": {}}::edge |
{"id": 1407374883553282, "label": "EMPLOYED", "end_id": 1125899906842626, "start_id": 844424930131970, "properties": {}}::edge |
{"id": 1407374883553283, "label": "EMPLOYED", "end_id": 1125899906842625, "start_id": 844424930131971, "properties": {}}::edge |
WHERE 句による結果のフィルター
WHERE 句を追加して、特定のノードまたはエッジに結果を絞り込みます。
会社 A のすべての従業員を検索します。
SELECT * FROM cypher('relation', $$
MATCH (p:Person)-[:EMPLOYED]->(a:Company)
WHERE a.name = '会社 A'
RETURN p
$$) AS (result_a agtype);結果:
| result_a |
|---|
{"id": 844424930131969, "label": "Person", "properties": {"name": "Zhang San"}}::頂点 |
{"id": 844424930131971, "label": "Person", "properties": {"name": "Wang Wu"}}::頂点 |
王五の学生を検索:
SELECT * FROM cypher('relation', $$
MATCH (p1:Person)-[:TEACHER]->(p2:Person)
WHERE p1.name = 'Wang Wu'
RETURN p2
$$) AS (result_a agtype);結果:
| result_a |
|---|
{"id": 844424930131969, "label": "Person", "properties": {"name": "Zhang San"}}::頂点 |
データの更新
MATCH を使用してノードまたはエッジを特定し、その後 SET を使用してそのプロパティを追加または更新します。
SELECT * FROM cypher('<graph_name>', $$
MATCH <pattern>
SET <property>
RETURN <variable>
$$) AS (result_a agtype);Zhang San の名前を Zhang 3 に更新します:
SELECT * FROM cypher('relation', $$
MATCH (p:Person {name: 'Zhang San'})
SET p.name = 'Zhang 3'
RETURN p
$$) AS (result_a agtype);結果:
| result_a |
|---|
{"id": 844424930131969, "label": "Person", "properties": {"name": "Zhang 3"}}::頂点 |
更新されたノードに gender プロパティを追加します。
SELECT * FROM cypher('relation', $$
MATCH (p:Person {name: 'Zhang 3'})
SET p.gender = 'male'
RETURN p
$$) AS (result_a agtype);結果:
| result_a |
|---|
{"id": 844424930131969, "label": "Person", "properties": {"name": "Zhang 3", "gender": "male"}}::vertex |
データの削除
プロパティの削除
REMOVE を使用して、ノードまたはエッジからプロパティを削除します。
SELECT * FROM cypher('<graph_name>', $$
MATCH <pattern>
REMOVE <property>
$$) AS (result_a agtype);「張三」から gender プロパティを削除します:
SELECT * FROM cypher('relation', $$
MATCH (p:Person {name: 'Zhang 3'})
REMOVE p.gender
RETURN p
$$) AS (result_a agtype);ノードの削除
エッジを持たないノードを削除するには、DELETE を使用します。
SELECT * FROM cypher('<graph_name>', $$
MATCH <pattern>
DELETE <variable>
$$) AS (result_a agtype);趙六という名前のノードを作成してから削除します。
-- Create the node.
SELECT * FROM cypher('relation', $$
CREATE (:Person {name: '趙六'})
$$) AS (result_a agtype);
-- Delete the node.
SELECT * FROM cypher('relation', $$
MATCH (p:Person {name: '趙六'})
DELETE p
$$) AS (result_a agtype);DELETE は、ノードにエッジが存在する場合に失敗します。ノードとそのすべてのエッジを一度に削除するには、代わりに DETACH DELETE を使用してください。
エッジの削除
WHERE 句で両端点を指定してエッジを一致させ、その後 DELETE で削除します。
趙六と会社 C への EMPLOYED エッジを作成してから、そのエッジを削除します。
-- Create the node and edge.
SELECT * FROM cypher('relation', $$
CREATE (ZhaoLiu:Person {name: '趙六'})
CREATE (ZhaoLiu)-[:EMPLOYED]->(:Company {name: '会社 C'})
$$) AS (result_a agtype);
-- Delete the edge.
SELECT * FROM cypher('relation', $$
MATCH (p:Person)-[r:EMPLOYED]->(c:Company)
WHERE p.name = '趙六' AND c.name = '会社 C'
DELETE r
$$) AS (result_a agtype);ノードとそのエッジの削除
ノードに関連するエッジが存在する場合は、DETACH DELETE を使用して、ノードとそのすべてのエッジを削除します。
SELECT * FROM cypher('<graph_name>', $$
MATCH <pattern>
DETACH DELETE <variable>
$$) AS (result_a agtype);趙六と EMPLOYED エッジを作成してから、両方を削除します。
-- Create the node and edge.
SELECT * FROM cypher('relation', $$
CREATE (ZhaoLiu:Person {name: '趙六'})
CREATE (ZhaoLiu)-[:EMPLOYED]->(:Company {name: '会社 C'})
$$) AS (result_a agtype);
-- Delete the node and its edges.
SELECT * FROM cypher('relation', $$
MATCH (p:Person {name: '趙六'})
DETACH DELETE p
$$) AS (result_a agtype);