このトピックでは、AnalyticDB for PostgreSQL でグラフ分析エンジンを作成および使用する方法について説明します。
Cypher とは
Cypher は、openCypher プロジェクトによって提供されるオープンソースの宣言型クエリ言語です。 SQL に似ていますが、グラフデータ構造向けに最適化されています。直感的で自然言語のような構文を使用して、Cypher はノード間の関係を明確に表現し、グラフマッチングパターンを定義できるため、効率的かつ容易なグラフデータクエリが可能になります。例:
MATCH (n:nodes)-[r:ARE_CONNECTED_TO]->(o:otherNodes)
RETURN n,r,o
上記の Cypher 文は、パターンマッチングを使用して、グラフ内で特定の条件を満たすすべてのノードとリレーションシップをクエリします。この文では、(n:nodes)
は、nodes
ラベルを持つ n という名前のノードを表します。[r:ARE_CONNECTED_TO]
は、ARE_CONNECTED_TO
ラベルを持つ r という名前のリレーションシップを表します。(o:otherNodes)
は、otherNodes
ラベルを持つ o という名前のターゲットノードを表します。この文は、このパターンに一致するすべてのソースノード、ターゲットノード、およびそれらのリレーションシップを返します。
構文
ノード構文
Cypher は、一対の括弧 ()
を使用してノードを表します。以下は、一般的なノード表現とその意味です。
()
:ラベルのない匿名ノード。任意のノードと一致します。(node)
:node
変数を持つノード。クエリ内のノードを参照するために使用されます。(:City)
:City
ラベルを持つノード。ラベルは、リレーショナルデータベースのテーブル名または分類識別子に似ており、特定の種類のノードをフィルタリングするために使用できます。(city:City)
:city
変数とCity
ラベルを持つノード。クエリ内のノードを参照し、ノードタイプを指定するために使用されます。(city:City {name: 'Hangzhou'})
:キーと値の形式で{name: 'Hangzhou'}
ラベルを持つノード。追加の特性を提供するために使用されます。これは、リレーショナルデータベースのWHERE
句と同様に、特定のラベル値を持つノードを正確に照合するのに役立ちます。(city:City {name: 'Hangzhou', province: 'Zhejiang'})
:複数のラベルを持つノード。複雑な条件フィルタリングを実装するために使用されます。
リレーションシップ構文
Cypher は、一対のハイフン(--
)を使用してリレーションシップを表します。方向付きリレーションシップは、-->
など、一端に矢印で示されます。角括弧([]
)を使用して、変数、タイプ、ラベルなど、詳細なリレーションシップを指定できます。以下は、一般的なリレーションシップ表現とその意味です。
--
:特定のタイプのない匿名の無方向リレーションシップ。-->
:特定のタイプのない匿名の方向付きリレーションシップ。-[role]->
:role
変数を持つリレーションシップ。クエリ内のリレーションシップを参照するために使用されます。-[:ACTED_IN]->
:ノードラベルと同様のACTED_IN
リレーションシップ。-[role:ACTED_IN]->
:role
変数を持つACTED_IN
リレーションシップ。-[role:ACTED_IN {roles: ['Neo']}]->
:{roles: ['Neo']}
ラベルを持つリレーションシップ。追加の特性を提供するために使用されます。
リレーションシップの角括弧の構文とセマンティクスは、ノードの括弧の構文に似ています。
変数:
role
などのリレーションシップ変数は、ノード変数に似ており、クエリ内の参照に使用されます。タイプ:
ACTED_IN
などのリレーションシップタイプは、ノードラベルに似ており、特定のリレーションシップを分類およびフィルタリングするために使用されます。ラベル:
{roles: ['Neo']}
などのリレーションシップラベルは、ノードラベルと機能的に同等であり、キーと値の形式で詳細なリレーションシップを指定するために使用されます。
パターン構文
ノードとリレーションシップの構文を統合して、豊富なセマンティック情報を伝えるパターンを構築できます。パターンの式の例:
(city_from:City {province: 'Zhejiang'})-[:NEXT_TO]-(city_next:City {province: 'Jiangsu'})
式の意味:
(city_from:City {province: 'Zhejiang'})
:province
がZhejiang
であるCity
ラベルを持つノード。(city_next:City {province: 'Jiangsu'})
:province
がJiangsu
であるCity
ラベルを持つノード。-[:NEXT_TO]-
:2 つの都市間の地理的隣接関係を指定するために使用されるNEXT_TO
無方向エッジ。
このパターンの式は、浙江省と江蘇省の間の隣接都市関係と一致します。パラメーターの説明:
city_from
とcity_next
は、それぞれ浙江省と江蘇省の都市ノードを表します。[:NEXT_TO]
は、2 つの都市間の地理的隣接関係を表します。
サポートされているバージョン
AnalyticDB for PostgreSQL V7.0 インスタンス V7.2.1.0 以降。
AnalyticDB for PostgreSQL コンソールのインスタンスの マイナーバージョン注:インスタンスのマイナーバージョンを更新する ページで を表示できます。インスタンスが必要なバージョンを満たしていない場合は、 してください。
前提条件
AnalyticDB for PostgreSQL インスタンスに 年齢拡張機能がインストールされている こと。
クエリを簡素化するために、search_path パラメーターで指定された検索パスに ag_catalog スキーマが追加されていること。次のいずれかの方法を使用できます。
セッションレベルの構成。
SET search_path TO public, ag_catalog;
データベースレベルの永続的な構成。
ALTER DATABASE <database_name> SET search_path TO public, ag_catalog;
(オプション) 初期アカウント または RDS_SUPERUSER 権限を持つ特権アカウント を使用して、他のユーザーに ag_catalog スキーマへのアクセス権を付与します。
GRANT USAGE ON SCHEMA ag_catalog TO <username>;
グラフ分析エンジンの作成と使用
グラフの作成
構文
create_graph()
関数を呼び出してグラフを作成します。
SELECT create_graph('<graph_name>');
パラメーター
graph_name
:グラフの名前。
例
SELECT create_graph('relation');
データの書き込み
構文
ag_catalog スキーマで cypher()
関数を呼び出して、ノードとリレーションシップを作成する式を記述します。
SELECT * FROM cypher('<graph_name>', $$
/* Cypher 式を記述します。*/
$$) AS (result_a agtype, result_b agtype);
例
次のグラフには、3 つの Person ノード (Zhang San、Li Si、Wang Wu) と 2 つの Company ノード (Company A と Company C) が含まれています。Person は EMPLOYED エッジを使用して Company に接続され、Person は FRIENDS エッジと TEACHER エッジを使用して互いに接続されています。
relation
グラフにデータを書き込みます。
SELECT * FROM cypher('relation', $$
CREATE (ZhangSan:Person {name: 'Zhang San'})
CREATE (LiSi:Person {name: 'Li Si'})
CREATE (WangWu:Person {name: 'Wang Wu'})
CREATE (company_a:Company {name: 'Company A'})
CREATE (company_c:Company {name: 'Company C'})
CREATE (ZhangSan)-[:EMPLOYED]->(company_a)
CREATE (LiSi)-[:EMPLOYED]->(company_c)
CREATE (WangWu)-[:EMPLOYED]->(company_a)
CREATE (ZhangSan)-[:FRIENDS]->(LiSi)
CREATE (WangWu)-[:TEACHER]->(ZhangSan)
$$) AS (result_a agtype)
データのクエリ
構文
MATCH
キーワードと RETURN
キーワードを使用してデータをクエリします。MATCH
は、ノード、リレーションシップ、およびそれらのプロパティを含む、一致させるグラフパターンを定義します。RETURN
は、クエリ結果で必要な戻りデータを指定します。
SELECT * FROM cypher('<graph_name>', $$
MATCH <patterns>
WHERE <expression> --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 (3 rows)
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 (3 rows)
部分データ (フィルタリングされたデータ) のクエリ
グラフでパターンマッチングを実行し、特定のデータを返すには、WHERE
句を使用して、条件に基づいて結果をフィルタリングします。
Company A のすべての従業員をクエリします。
SELECT * FROM cypher('relation', $$ MATCH (p:Person)-[:EMPLOYED]->(a:Company) WHERE a.name='Company A' RETURN p $$) AS (result_a agtype);
結果の例:
result_a ----------------------------------------------------------------------------------------- {"id": 844424930131969, "label": "Person", "properties": {"name": "Zhang San"}}::vertex {"id": 844424930131971, "label": "Person", "properties": {"name": "Wang Wu"}}::vertex (2 rows)
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"}}::vertex (1 row)
データの更新 (ノードまたはエッジ)
グラフ内の既存のデータ (ノードやリレーションシップなど) を変更するには、ターゲットオブジェクトを照合し、SET
キーワードを使用してデータを追加または更新します。
構文
SELECT * FROM cypher('<graph_name>', $$
MATCH <patterns>
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"}}::vertex (1 row)
値が male の gender ラベルを Zhang San に追加します。
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 (1 row)
データの削除
ラベルの削除
ノードまたはエッジラベルが不要になった場合は、REMOVE
キーワードを使用してラベルを削除できます。
構文
SELECT * FROM cypher('<graph_name>', $$
MATCH <patterns>
REMOVE <property>
$$) AS (result_a agtype);
例
Zhang San から 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 <patterns>
DELETE <variable>
$$) AS (result_a agtype);
例
Zhao Liu という名前のノードを作成し、そのノードを削除します。
-- Zhao Liu という名前のノードを作成します。
SELECT * FROM cypher('relation', $$
CREATE (:Person {name: 'Zhao Liu'})
$$) AS (result_a agtype)
-- ノードを削除します。
SELECT * FROM cypher('relation', $$
MATCH(p:Person {name: 'Zhao Liu'})
DELETE p
$$) AS (result_a agtype)
エッジを持つノードを直接削除することはできません。代わりに、DETACH DELETE
文を実行して、ノードとそのエッジを削除 します。
エッジの削除
Zhao Liu という名前のノードと、Zhao Liu と Company C の間の EMPLOYED エッジを作成します。次に、WHERE
句で Person 名と Company 名を指定して、エッジを削除します。
-- Zhao Liu という名前のノードと、Zhao Liu と Company C の間の EMPLOYED エッジを作成します。
SELECT * FROM cypher('relation', $$
CREATE (ZhaoLiu:Person {name: 'Zhao Liu'})
CREATE (ZhaoLiu)-[:EMPLOYED]->(:Company {name: 'Company C'})
$$) AS (result_a agtype);
-- エッジを削除します。
SELECT * FROM cypher('relation', $$
MATCH (p:Person)-[r:EMPLOYED]->(c:Company)
WHERE p.name='Zhao Liu' AND c.name='Company C'
DELETE r
$$) AS (result_a agtype);
ノードとそのエッジの削除
エッジを持つノードを直接削除することはできません。代わりに、DETACH DELETE
文を実行して、ノードとそのエッジを削除します。
構文
SELECT * FROM cypher('<graph_name>', $$
MATCH <patterns>
DETACH DELETE <variable>
$$) AS (result_a agtype);
例
Zhao Liu という名前のノードと、Zhao Liu と Company C の間の EMPLOYED エッジを作成します。次に、エッジと Zhao Liu ノードを削除します。
-- Zhao Liu という名前のノードと、Zhao Liu と Company C の間の EMPLOYED エッジを作成します。
SELECT * FROM cypher('relation', $$
CREATE (ZhaoLiu:Person {name: 'Zhao Liu'})
CREATE (ZhaoLiu)-[:EMPLOYED]->(:Company {name: 'Company C'})
$$) AS (result_a agtype);
-- ノードとそのエッジを削除します。
SELECT * FROM cypher('relation', $$
MATCH (p:Person {name: 'Zhao Liu'})
DETACH DELETE p
$$) AS (result_a agtype);