18.3 グラフ・サーバー(PGX)でサポートされているPGQL機能および制限事項

グラフ・サーバー(PGX)でサポート対象のPGQL機能、およびサポート対象外のPGQL機能について学習します。

表18-2 グラフ・サーバー(PGX)でサポートされているPGQL機能および制限事項

機能 グラフ・サーバー上のPGQL (PGX)
CREATE PROPERTY GRAPH サポート対象
制限事項:
  • 頂点のコンポジット・キーはありません
DROP PROPERTY GRAPH サポート対象外
固定長パターン一致 サポート対象
可変長パターン一致の目標 サポート対象:
  • 到達可能性
  • パス検索接頭辞:
    • ANY
    • ANY SHORTEST
    • SHORTEST k
    • ALL SHORTEST
    • ANY CHEAPEST
    • CHEAPEST k
    • ALL
  • パス・モード:
    • WALK
    • TRAIL
    • SIMPLE
    • ACYCLIC
可変長パターン一致の数量詞 サポート対象:
  • *
  • +
  • ?
  • { n }
  • { n, }
  • { n, m }
  • { , m }

制限事項:

  • ?は到達可能性についてのみサポートされています
  • ANY CHEAPESTおよびTOP k CHEAPESTの場合は、*のみがサポートされています
可変長パスのネスト解除 サポート対象:
  • ONE ROW PER VERTEX
  • ONE ROW PER STEP

制限事項:

  • *数量詞はサポートされていません
GROUP BY サポート対象
HAVING サポート対象
集計 サポート対象:
  • COUNT
  • MINMAXAVGSUM
  • LISTAGG
  • ARRAY_AGG

サポート対象外

  • JSON_ARRAYAGG
DISTINCT
  • SELECT DISTINCT
  • DISTINCTを使用した集計(COUNT(DISTINCT e.prop)など)
サポート対象
SELECT v.* サポート対象
ORDER BY (+ASC/DESC)、LIMIT、OFFSET サポート対象
データ型 サポート対象:
  • INTEGER (32ビット)
  • LONG (64ビット)
  • FLOAT (32ビット)
  • DOUBLE (64ビット)
  • STRING (最大長なし)
  • BOOLEAN
  • DATE
  • TIME
  • TIMEWITHTIMEZONE
  • TIMESTAMP
  • TIMESTAMPWITHTIMEZONE
JSON 組込みのJSONサポートはありません。ただし、JSON値はSTRINGとして格納でき、JavaまたはJavaScriptで記述されたユーザー定義関数(UDF)を使用して操作または問合せできます。
演算子 サポート対象:
  • 関係: +-*/%- (単項マイナス)
  • 算術: =<><><=>=
  • 論理: ANDORNOT
  • 文字列: || (concat)
関数および述語 サポート対象:
  • IS NULLIS NOT NULL
  • JAVA_REGEXP_LIKE (CONTAINSに基づいています)
  • LOWERUPPER
  • SUBSTRING
  • ABSCEIL/CEILINGFLOORROUND
  • EXTRACT
  • ID, VERTEX_ID, EDGE_ID
  • LABELLABELSIS [NOT] LABELED
  • ALL_DIFFERENT
  • IN_DEGREEOUT_DEGREE
  • CAST
  • CASE
  • INNOT IN
  • MATCHNUM
  • ELEMENT_NUMBER
  • IS [NOT] SOURCE [OF]IS [NOT] DESTINATION [OF]
  • VERTEX_EQUALEDGE_EQUAL
ユーザー定義関数 サポート対象:
  • Java UDF
  • JavaScript UDF
副問合せ:
  • スカラー副問合せ
  • EXISTSおよびNOT EXISTS副問合せ
  • LATERAL副問合せ
サポート対象

制限事項

FROM句にLATERAL副問合せが含まれている場合、LATERAL副問合せはFROM句の最初の表式である必要があります。FROM句には、追加のMATCH句を含めることができますが、追加のLATERAL副問合せまたはGRAPH_TABLE演算子を含めることはできません。

GRAPH_TABLE演算子 サポート対象

制限事項

FROM句にGRAPH_TABLE演算子が含まれている場合、GRAPH_TABLE演算子はFROM句の最初の表式である必要があります。FROM句には、追加のMATCH句を含めることができますが、追加のLATERAL副問合せまたはGRAPH_TABLE演算子を含めることはできません。

INSERT/UPDATE/DELETE サポート対象
INTERVALリテラルおよび操作

サポートされているリテラル:

  • SECOND
  • MINUTE
  • HOUR
  • DAY
  • MONTH
  • YEAR

サポートされている操作:

  • INTERVALを日時に追加します(+)
  • INTERVALを日時から減算します(-)

また、次では、特定のサポートされているPGQL機能とサポートされていないPGQL機能についても説明します:

18.3.1 すべてのプロパティの選択のサポート

SELECT v.*を使用して、変数vにバインドする頂点またはエッジのすべてのプロパティを選択できます。たとえば:

SELECT label(n), n.* FROM MATCH (n) ORDER BY "number", "name"

実行時に、問合せ出力は次のようになります。

+-----------------------------+
| label(n) | number | name    |
+-----------------------------+
| Account  | 1001   | <null>  |
| Account  | 2090   | <null>  |
| Account  | 8021   | <null>  |
| Account  | 10039  | <null>  |
| Person   | <null> | Camille |
| Person   | <null> | Liam    |
| Person   | <null> | Nikita  |
| Company  | <null> | Oracle  |
+-----------------------------+

ラベル式を使用して、指定した頂点ラベルまたはエッジ・ラベルに属するプロパティを選択できます。たとえば:

SELECT label(n), n.* FROM MATCH (n:Person) ORDER BY "name"

前述の問合せは、指定されたPersonラベルのすべてのプロパティを取得します。

+--------------------+
| label(n) | name    |
+--------------------+
| Person   | Camille |
| Person   | Liam    |
| Person   | Nikita  |
+--------------------+

複数の変数を使用してすべてのプロパティを選択した場合、列名が重複しないようにPREFIXを指定することもできます。たとえば:

SELECT n.* PREFIX 'n_', e.* PREFIX 'e_', m.* PREFIX 'm_'
FROM MATCH (n:Account) -[e:transaction]-> (m:Account)
ORDER BY "e_amount"

問合せの出力は次のようになります。

+--------------------------------+
| n_number | e_amount | m_number |
+--------------------------------+
| 10039    | 1000.0   | 8021     |
| 8021     | 1500.3   | 1001     |
| 8021     | 3000.7   | 1001     |
| 2090     | 9900.0   | 10039    |
| 1001     | 9999.5   | 2090     |
+--------------------------------+

18.3.2 可変長パス問合せのネスト解除

可変長パス問合せ(SHORTESTパスやCHEAPESTパスなど)のネストを解除して、パスに沿った頂点またはエッジごとに個別の行を取得できます。

次のオプションのいずれかを使用して、パス集計をネスト解除できます。
  • ONE ROW PER MATCH (デフォルト・オプション)
  • ONE ROW PER VERTEX(vertex_variable)
  • ONE ROW PER STEP(edge_source_variable,edge_variable,edge_destination_variable)

たとえば、次のPGQL問合せではONE ROW PER STEPオプションを使用します。

SELECT  v1.ACCT_ID AS src_no, k.TXN_AMOUNT, v2.ACCT_ID AS dest_no 
FROM MATCH ALL SHORTEST (a:Accounts) -[e:transfers]->+ (b:Accounts)
ONE ROW PER STEP( v1,k,v2 )
WHERE a.ACCT_ID = 284 AND b.ACCT_ID = 616

ONE ROW PER STEPオプションは、最小ホップが0より大きいパスのみをサポートするため、*修飾子はこのオプションでサポートされていないことに注意してください。

実行すると、前述の問合せでは、対応するソース頂点および宛先頂点によってバインドされているパス上のエッジごとに1行を取得します。

+-------------------------------+
| src_no | TXN_AMOUNT | dest_no |
+-------------------------------+
| 744    | 1000.0     | 616     |
| 772    | 1000.0     | 744     |
| 284    | 1000.0     | 772     |
| 744    | 1000.0     | 616     |
| 772    | 1500.0     | 744     |
| 284    | 1000.0     | 772     |
+-------------------------------+

グラフ・ビジュアライゼーション・ツールを使用して、パスに沿ってONE ROW PER STEPを使用してエッジを視覚化することもできます。

図18-1 可変長パス問合せのネスト解除の視覚化

図18-1の説明が続きます
「図18-1 可変長パス問合せのネスト解除の視覚化」の説明

ONE ROW PER VERTEXオプションを指定した問合せの例を次に示します。

SELECT k.acct_id AS id, k.acct_name AS name
FROM MATCH ANY SHORTEST (a:Accounts) ((src:Accounts)-[e:transfers]->){1,3}(b:Accounts)
ONE ROW PER VERTEX(k)
WHERE a.acct_id=284 AND b.acct_id=616

実行時には、前述の問合せはパスに沿って頂点ごとに1行を取得します。

+----------------+
| id  | name     |
+----------------+
| 616 | Account4 |
| 744 | Account3 |
| 772 | Account2 |
| 284 | Account1 |
+---------------+

再帰的なパスのネスト解除問合せ用の組込み関数のサポート

PGQLは、次の2つの組込み関数をサポートしており、これらはパスのネスト解除オプション(ONE ROW PER VERTEXONE ROW PER STEPまたはONE ROW PER MATCH)のいずれかと組み合せて使用できます。

  • MATCH_NUMBER(k): ネスト解除されたパスごとに一意のパス単位の識別子を戻します(つまり、2つの行の元が同じパスである場合、それらのMATCH_NUMBER(k)は同じです)。
  • ELEMENT_NUMBER(k): パスに沿って頂点またはエッジの要素番号を戻します。左端の頂点には1、2番目には3、その次には5のように、頂点には奇数の番号が付けられます。左端のエッジには2、次のエッジには4のように、エッジには偶数の番号が割り当てられます。

たとえば、次のPGQL問合せでは、ONE ROW PER VERTEXオプションを指定してMATCH_NUMBER(k)およびELEMENT_NUMBER(k)関数を使用します。

SELECT k.*, match_number(k), element_number(k)
FROM MATCH ANY SHORTEST (a:Accounts) -[e:transfers]->* (b:Accounts) ONE ROW PER VERTEX ( k )
WHERE a.acct_id = 284 AND b.acct_id = 616

前述の問合せを実行すると、次の出力が生成されます。頂点に対して戻されたelement_number(k)は奇数の値であることに注意してください。前述の問合せではANYパス・パターンを使用しているため、出力には任意のパスが1つのみ表示されます。このため、match_number(k)はパス内のすべての行で同じです。

+-----------------------------------------------------------+
| ACCT_ID | ACCT_NAME | match_number(k) | element_number(k) |
+-----------------------------------------------------------+
| 616     | Account   | 0               | 7                 |
| 744     | Account   | 0               | 5                 |
| 772     | Account   | 0               | 3                 |
| 284     | Account   | 0               | 1                 |
+-----------------------------------------------------------+

次の例に、ONE ROW PER STEPオプションを指定してMATCH_NUMBER(k)およびELEMENT_NUMBER(k)関数を使用したPGQL問合せを示します。

SELECT v1.acct_id AS src_no,k.txn_amount,v2.acct_id AS dest_no, match_number(k), element_number(k)
FROM MATCH ALL SHORTEST (a:Accounts) -[e:transfers]->+ (b:Accounts)
ONE ROW PER STEP( v1,k,v2 )
WHERE a.acct_id = 284 AND b.acct_id = 616

前述の問合せ出力は次のようになります。match_number(k)で識別されたパスが2つあり、エッジは偶数のelement_number(k)値とともに表示されています。

+---------------------------------------------------------------------+
| src_no | txn_amount | dest_no | match_number(k) | element_number(k) |
+---------------------------------------------------------------------+
| 744    | 1000.0     | 616     | 0               | 6                 |
| 772    | 1000.0     | 744     | 0               | 4                 |
| 284    | 1000.0     | 772     | 0               | 2                 |
| 744    | 1000.0     | 616     | 1               | 6                 |
| 772    | 1500.0     | 744     | 1               | 4                 |
| 284    | 1000.0     | 772     | 1               | 2                 |
+---------------------------------------------------------------------+

18.3.3 PGQL問合せでのINTERVALリテラルの使用

PGQL問合せでINTERVALリテラルを使用すると、PGQL Temporalデータ型に対する間隔の加算または減算をそれぞれ実行できます。

サポートされるTemporalデータ型については、PGQL 1.5 Specificationを参照してください。

INTERVAL型は期間で、キーワード"INTERVAL"とそれに続く数値および時間単位で構成されます。たとえば、INTERVAL '1' DAYとなります。

次の表に、INTERVAL値でサポートされる有効な時間単位を示します。

表18-3 INTERVAL値のフィールドの有効な値

キーワード サポートされる有効な値
YEAR <間隔先行フィールド精度>以外は制約なし
MONTH 月(年単位) (0-11)
DAY <間隔先行フィールド精度>以外は制約なし
HOUR 時間(日単位) (0-23)
MINUTE 分(時間単位) (0-59)
SECOND 秒(分単位) (0-59.999...)

次のINTERVAL操作がTemporalデータ型でサポートされています。

  • TEMPORAL TYPE + INTERVAL
  • INTERVAL + TEMPORAL TYPE
  • TEMPORAL TYPE - INTERVAL

たとえば、次のPGQL問合せでは、n.birthdate + INTERVAL '20' YEAR > TIMESTAMP '2000-01-01 00:00:00'である個人を取得します。

opg4j> graph.queryPgql("SELECT n.name, n.birthdate FROM MATCH (n:Person) WHERE n.birthdate + INTERVAL '20' YEAR > TIMESTAMP '2000-01-01 00:00:00'").print()
graph.queryPgql("SELECT n.name, n.birthdate FROM MATCH (n:Person) WHERE n.birthdate + INTERVAL '20' YEAR > TIMESTAMP '2000-01-01 00:00:00'").print();
graph.query_pgql("SELECT n.name, n.birthdate FROM MATCH (n:Person) WHERE n.birthdate + INTERVAL '20' YEAR > TIMESTAMP '2000-01-01 00:00:00'").print()

実行時に、問合せ出力は次のようになります。

+--------------------------+
| name  | birthdate        |
+--------------------------+
| Mary  | 1982-09-25T00:00 |
| Alice | 1987-02-01T00:00 |
+--------------------------+

18.3.4 PGQLでのパス・モードの使用

次のパス・モードは、ANYALLANY SHORTESTSHORTEST k、およびALL SHORTESTと組み合せて使用できます。

  • WALK (デフォルト・パス・モード):ウォークは、一連の頂点とエッジを介してグラフをトラバースします。ウォークでアクセスした頂点とエッジを繰り返すことができます。したがって、このデフォルトのパス・モードではパスのフィルタリングは行われません。
  • TRAIL:トレイルはエッジを繰り返すことなくグラフをトラバースしています。したがって、エッジを繰り返すパス・バインディングは返されません。
    SELECT CAST(a.number AS STRING) || ' -> ' || LISTAGG(x.number, ' -> ') AS accounts_along_path
    FROM MATCH ALL TRAIL PATHS (a IS account) (-[IS transaction]-> (x)){2,} (b IS Account)
    WHERE a.number = 8021 AND b.number = 1001
    
    +-----------------------------------------------+
    | accounts_along_path                           |
    +-----------------------------------------------+
    | 8021 -> 1001 -> 2090 -> 10039 -> 8021 -> 1001 |
    | 8021 -> 1001 -> 2090 -> 10039 -> 8021 -> 1001 |
    +-----------------------------------------------+
    前述の出力では、両方のパスに頂点8021と1001が2回含まれていますが、エッジが繰り返されないかぎり、まだトレイルは有効です。
  • ACYCLIC:グラフ・トラバースの開始頂点と終了頂点が異なる場合、これはパスにサイクルがないことを意味します。この場合、頂点が繰り返されるパス・バインディングは返されません。
    SELECT CAST(a.number AS STRING) || ' -> ' || LISTAGG(x.number, ' -> ') AS accounts_along_path
    FROM MATCH SHORTEST 10 ACYCLIC PATHS (a IS account) (-[IS transaction]-> (x))+ (b)
    WHERE a.number = 10039 AND b.number = 1001
    
    +-----------------------+
    | accounts_along_path   |
    +-----------------------+
    | 10039 -> 8021 -> 1001 |
    | 10039 -> 8021 -> 1001 |
    +-----------------------+
    前述の問合せで、10の最短パスがリクエストされました。ただし、他のすべてのパスが循環するため、2つのみが返されます。
  • SIMPLE: 単純なウォークは、頂点を繰り返さずにグラフをトラバースします。したがって、頂点を繰り返すパス・バインディングは返されません。唯一の例外は、繰り返される頂点がパスの最初の頂点と最後の頂点であることです。
    SELECT CAST(a.number AS STRING) || ' -> ' || LISTAGG(x.number, ' -> ') AS accounts_along_path
    FROM MATCH ANY SIMPLE PATH (a IS account) (-[IS transaction]-> (x))+ (a)
    WHERE a.number = 10039
    
    +----------------------------------------+
    | accounts_along_path                    |
    +----------------------------------------+
    | 10039 -> 8021 -> 1001 -> 2090 -> 10039 |
    +----------------------------------------+
    前述の問合せは循環パスを返します。このパスは、同じ頂点で開始および終了し、パスに他のサイクルがないため、有効かつ単純なパスです。

パス・モードは、構文的にはANYALLANY SHORTESTSHORTEST kALL SHORTESTCHEAPESTおよびCHEAPEST kの後に配置されます。パス・モードの後には、PATHまたはPATHSキーワードが続くこともあります。

すべての無限量数量詞に対してTRAILACYCLICまたはSIMPLEの一致パス・モードを使用すると、グラフ・パターン一致の結果セットが有限であることが保証されます。

18.3.5 PGQL Lateral副問合せのサポート

LATERAL副問合せを使用して、ある問合せの出力行を別の問合せに渡すことができます。サポートされているのは単一のLATERAL副問合せのみです。

たとえば、別のORDER BY句またはGROUP BY句の上にORDER BY句またはGROUP BY句を使用できます。

/* Find the top-5 largest transactions and return the account number
   that received the highest number of such large transactions */
SELECT recipient, COUNT(*) AS num_large_transactions
FROM LATERAL ( SELECT m.number AS recipient
               FROM MATCH (n:account) -[e:transaction]-> (m:account)
               ORDER BY e.amount DESC
               LIMIT 5 )
GROUP BY recipient
ORDER BY num_large_transactions DESC
LIMIT 1

また、FROM句のLATERAL副問合せの後に1つ以上のMATCH句を指定できます。たとえば:

SELECT path_num, elem_num, owner.name
FROM LATERAL ( SELECT v, MATCHNUM(v) AS path_num, ELEMENT_NUMBER(v) AS elem_num
               FROM MATCH SHORTEST 2 PATHS (a1:account) -[e:transaction]->* (a2:account)
                      ONE ROW PER VERTEX ( v )
               WHERE a1.number = 10039 AND a2.number = 2090 )
    , MATCH (v) -[:owner]-> (owner:Person|Company)
ORDER BY path_num, elem_num 

FROM句にLATERAL副問合せが含まれている場合、LATERAL副問合せはFROM句の最初の表式である必要があることに注意することが重要です。FROM句には追加のMATCH句を含めることができますが、追加のLATERAL副問合せを含めることはできません。

18.3.6 PGQL GRAPH_TABLE演算子のサポート

PGQLのGRAPH_TABLE演算子によって、グラフ・サーバー(PGX)にロードされるグラフとデータベース上のグラフの間の相互運用性が向上します。

ただし、SQL標準に準拠するには、PGQL問合せ構文が次のように整理されている必要があります。
  • グラフ・パターンMATCH問合せのラベル述語では、ISキーワードを使用する必要があります。
  • 出力行数を制限するには、LIMIT x句のかわりにFETCH [FIRST/NEXT] x [ROW/ROWS]句を使用します。
  • エッジの方向を確認するには、[NOT] is_source_of(e, v) / [NOT] is_destination_of(e, v)のかわりにv IS [NOT] SOURCE [OF] e/v IS [NOT] DESTINATION [OF] eを標準フォームとして使用します。
  • 頂点またはエッジに指定したラベルがあるかどうかを確認するには、has_label(x, <label_string>)の代替としてx IS [NOT] LABELED <label_string>述語を使用します。
  • kの最短パスと一致させるには、MATCH (n) –[e]->* (m) KEEP SHORTEST kMATCH TOP k SHORTEST (n) –[e]->* (m)の標準形式として使用します。
  • 固定長パス・パターンの前にはALLキーワード(オプション)があります。

    MATCH ALL (n) –[e]->{1,4} (m)の代替としてのMATCH (n) –[e]->{1,4} (m)

  • MATCH <path pattern prefix> <path pattern> <WHERE clause>の代替としてのMATCH <path pattern> KEEP <path pattern prefix> <WHERE clause>

次に、GRAPH_TABLE演算子を使用した問合せの例をいくつか示します:

例18-2 TRAILパス・モードとALLを使用した集計問合せ

SELECT *
FROM GRAPH_TABLE ( financial_transactions
       MATCH ALL TRAIL (a IS account) -[e IS transaction]->* (b IS account)
       /* optional ONE ROW PER VERTEX/STEP clause here */
       WHERE a.number = 8021 AND b.number = 1001
       COLUMNS ( LISTAGG(e.amount, ', ') AS amounts )
     )ORDER BY amounts

この問合せの出力は次のようになります。

+----------------------------------------+
| amounts                                |
+----------------------------------------+
| 1500.3                                 |
| 1500.3, 9999.5, 9900.0, 1000.0, 3000.7 |
| 3000.7                                 |
| 3000.7, 9999.5, 9900.0, 1000.0, 1500.3 |
+----------------------------------------+

例18-3 KEEP句を使用した集計問合せ

SELECT *
FROM GRAPH_TABLE ( financial_transactions
       MATCH (a IS Account) -[e IS transaction]->+ (a)
       KEEP SIMPLE PATHS
       WHERE a.number = 10039
       COLUMNS ( LISTAGG(e.amount, ', ') AS amounts_along_path,
                 SUM(e.amount) AS total_amount )
     )
ORDER BY total_amount DESC

この問合せの出力は次のようになります。

+-----------------------------------------------+
| amounts_along_path             | total_amount |
+-----------------------------------------------+
| 1000.0, 3000.7, 9999.5, 9900.0 | 23900.2      |
| 1000.0, 1500.3, 9999.5, 9900.0 | 22399.8      |
+-----------------------------------------------+

18.3.7 数量詞の制限

到達可能性パターンと最短パス・パターンでは、*+{1,4}などのすべての数量詞がサポートされていますが、最小コスト・パス・パターンでサポートされている数量詞は* (ゼロ以上)のみです。

18.3.8 定量化されたパターンでのWHERE句およびCOST句の制限事項

到達可能性パターンや最短パス・パターンおよび最小コスト・パス・パターンなどの定量化されたパターンのWHERE句およびCOST句は、単一の変数の参照のみに制限されます。

次に、WHERE句またはCOST句が、zeroまたはoneのかわりに2つの変数eおよびxを参照しているためにサポートされていない問合せの例を示します。

... PATH p AS (n) –[e]-> (m) WHERE e.prop > m.prop ...
... SHORTEST ( (n) (-[e]-> (x) WHERE e.prop + x.prop > 10)* (m) ) ...
... CHEAPEST ( (n) (-[e]-> (x) COST e.prop + x.prop )* (m) ) ...

次の問合せがサポートされているのは、副問合せは外部スコープから単一の変数aのみを参照し、変数cは副問合せで新たに導入されたためにカウントされないためです。

... PATH p AS (a) -> (b)
      WHERE EXISTS ( SELECT * FROM MATCH (a) -> (c) ) ...