すべてのプロダクト
Search
ドキュメントセンター

AnalyticDB:グラフ分析エンジンの作成と使用

最終更新日:Dec 27, 2025

このトピックでは、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'})City ラベルと、province プロパティが 'Zhejiang' であるノードを表します。これは浙江省にある都市です。

  • (city_next:City {province: 'Jiangsu'})City ラベルと、province プロパティが 'Jiangsu' である別のノードを表します。これは江蘇省にある都市です。

  • -[:NEXT_TO]-:タイプが NEXT_TO の無向エッジを表します。これは、2つの都市が地理的に隣接していることを示します。

このパターン式は、浙江省と江蘇省の隣接する都市間のリレーションシップに一致します。

  • city_fromcity_next は、それぞれ浙江省と江蘇省の都市ノードを表します。

  • [:NEXT_TO] は、2つの都市間の地理的な隣接関係を表します。

バージョンの制限事項

AnalyticDB for PostgreSQL V7.0 インスタンスの V7.2.1.0 以降。

説明

AnalyticDB for PostgreSQL コンソールのインスタンスの [基本情報] ページでマイナーバージョンを確認できます。ご利用のインスタンスが必要なバージョンを満たしていない場合は、インスタンスのマイナーバージョンを更新してください。

前提条件

  • AnalyticDB for PostgreSQL インスタンスに age 拡張機能がインストールされていること。

    age 拡張機能は、マイナーエンジンバージョンが 7.2.1.4 以降の AnalyticDB for PostgreSQL V7.0 インスタンスに自動的にインストールされます。

  • クエリを簡略化するために、`ag_catalog` スキーマが `search_path` パラメーターで指定された検索パスに追加されていること。次のいずれかのメソッドを使用できます。

    • セッションレベルの構成。

      SET search_path TO "$user", public, ag_catalog;
    • データベースレベルの永続的な構成。

      ALTER DATABASE <database_name> SET search_path TO "$user", 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 つの人物ノード (Zhang San、Li Si、Wang Wu) と 2 つの会社ノード (会社 A、会社 C) が含まれています。人物と会社は EMPLOYED エッジで接続され、人物同士は FRIENDS エッジおよび TEACHER エッジで接続されています。

image

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 行)
  • 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 句を使用して、条件に基づいて一致した結果をフィルターできます。

  • 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"}}::頂点
    (2 行)
  • ワン・ウーの学生を照会します。

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

データ (ノードまたはエッジ) の更新

ノードやリレーションシップを含むグラフ内の既存のデータについて、ターゲットオブジェクトを照合し、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 行)
  • Zhang San に、値が male の 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": "田中三郎", "gender": "male"}}::vertex
    (1 row)

データの削除

ラベルの削除

ノードまたはエッジのラベルが不要になった場合、REMOVE キーワードを使用して削除できます。

構文

SELECT * FROM cypher('<graph_name>', $$
  MATCH <patterns>
  REMOVE <property>
$$) AS (result_a agtype);

Zhang San から性別ラベルを削除します。

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 に雇用されていることを示すエッジを追加します。次に、その雇用関係を削除します。関係を削除するには、WHERE 句で人物名と会社名を指定します。

-- Zhao Liu という名前のノードと、Zhao Liu と 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 という名前のノードと、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);