GQL グラフ パターン

グラフ パターンは、Microsoft Fabric のグラフにおける GQL クエリの主要な構成要素です。 これらは、直感的で視覚的な方法でノードとエッジを使用して、グラフ内で探している構造を記述します。 グラフ パターンは、クエリ エンジンがグラフ内の実際のデータと照合しようとするテンプレートと考えてください。

この記事では、GQL のグラフ パターンの構文と構成規則について説明します。

Important

この記事では、 ソーシャル ネットワークのグラフ データセットの例のみを使用します。

単純な要素パターン

単純な要素パターンは、特定の要件を満たすグラフの個々のノードとエッジを照合するのに役立ちます。 これらのパターンは、より複雑なパターン マッチングの基礎を形成します。

単純なノード パターン

ノード パターンは、ノードが一致する必要があるラベルとプロパティを指定します。

(:Place&City { name: "New York" })

このパターンは、ラベルとPlaceラベル (City 演算子で示されます) の&を持ち、name プロパティが"New York"等しいすべてのノードと一致します。 この必要なラベルとプロパティの組み合わせは、ノード パターンの フィラー と呼ばれます。

主な概念:

  • ラベルの一致: 複数のラベルを要求するには、 & を使用します。
  • プロパティのフィルター処理: プロパティが一致する必要がある正確な値を指定します。
  • 柔軟な ("共変") 一致: 一致するノードは、指定されたラベルとプロパティを超えるラベルとプロパティを持つことができます。

注

ノードは複数のラベルを持つことができますが、複数のラベルを持つエッジの種類はまだサポートされていません。

シンプルなエッジ パターン

エッジ パターンは、ノード パターンよりも複雑です。 フィラーを指定するだけでなく、原点ノードパターンをターゲットノードパターンに接続します。 エッジ パターンでは、エッジとそのエンドポイントの両方の要件について説明します。

(:Person)-[:likes|knows { creationDate: ZONED_DATETIME("2010-08-31T13:16:54Z") }]->(:Comment)

矢印の方向 -[...]-> は重要で、 (:Person) を原点ノードパターン、 (:Comment) をターゲットノードパターンとして決定します。 エッジの方向を理解することは、グラフのクエリを正しく行う上で非常に重要です。

同等のミラー化されたパターン:

矢印を反転し、ノード パターンを入れ替えて、同等のミラー化されたエッジ パターンを作成できます。

(:Comment)<-[:likes { creationDate: ZONED_DATETIME("2010-08-31T13:16:54Z") }]-(:Person)

このパターンは、同じリレーションシップを検出しますが、逆の観点から見ると見なされます。

任意向きのエッジ パターン

グラフ エッジの方向がクエリに関係ない場合は、任意の方向のエッジ パターンを作成することで、その方向を指定しないようにすることができます。

(:Song)-[:inspired]-(:Movie)

このパターンは、どのノードが原点でどちらがターゲットであっても、 (:Song)-[:inspired]->(:Movie) と (:Movie)-[:inspired]->(:Song) を合わせた際と同じエッジに一致します(この例はソーシャルネットワークグラフタイプからのものではありません)。

グラフ エッジ パターンのショートカット

GQL には、クエリをより簡潔にするために、一般的なエッジ パターンに便利なショートカットが用意されています。

  • ()->() は、 ()-[]->() (任意のラベルを持つ有向エッジ) を表します。
  • ()<-() は、 ()<-[]-() を表します (任意のラベルと逆の方向のエッジ)
  • ()-() は、 ()-[]-() (任意のラベルを持つ任意の向きのエッジ) を表します

これらのショートカットは、接続性を考慮するが、特定のグラフ エッジの種類については考慮しない場合に役立ちます。

ラベル式

パターンは、一致するノードとエッジのラベルに複雑な要件を表すことができます。

Example:

MATCH (:Person|(Organization&!Company))-[:isLocatedIn]->(p:City|Country)
RETURN count(*) AS num_matches

これにより、isLocatedInノードまたはPersonノードにOrganizationノードまたはCompanyUniversityノード (ソーシャル ネットワーク スキーマ内のノードは常にCity) を接続するCountryエッジの数がカウントされます。

構文 :

構文 Meaning
A&B ラベルには、A と B の両方を含める必要があります。
A\|B ラベルには、A または B の少なくとも 1 つを含める必要があります。
!A ラベルは A を除外する必要があります。

さらに、かっこを使用して、ラベル式の評価の順序を制御します。 既定では、 ! は最も優先順位が高く、 & は |よりも優先順位が高くなります。 したがって、 !A&B|C|!D は ((!A)&B)|C|(!D)と同じです。

変数のバインド

変数を使用すると、クエリの他の部分で一致するグラフ要素を参照できます。 強力なクエリを作成するには、変数をバインドして使用する方法を理解することが不可欠です。

要素変数のバインド

ノード パターンとエッジ パターンの両方で、後で参照できるように、一致するノードとエッジを変数にバインドできます。

(p:Person)-[w:workAt]->(c:Company)

このパターンでは、pは一致するPerson ノードにバインドされ、一致するwエッジにworkAtされ、一致するc ノードにCompanyされます。

構造上の制約に対する変数の再利用:

パターン内で同じ変数を複数回再利用すると、一致の構造に対する制限が表されます。 同じ変数が出現するたびに、有効な一致で常に同じグラフ要素にバインドする必要があります。 変数の再利用は、複雑な構造要件を表現するために強力です。

(c:Company)<-[:workAt]-(x:Person)-[:knows]-(y:Person)-[:workAt]->(c:Company)

このパターンは、互いを認識し、変数Personにバインドされている同じxで動作するyとCompanycノードを検索します。 cを再利用することで、両方のユーザーが同じ会社で作業できるようになります。

要素変数を持つパターン述語:

要素変数をバインドすると、ノードとエッジ パターンの述語を指定できます。 { name: "New York, USA" }のような正確なプロパティ値を入力者に提供する代わりに、入力者は候補要素ごとに評価される述語を指定できます。 このパターンは、述語が TRUEに評価された場合にのみ一致します。

(p:Person)-[e:knows WHERE e.creationDate >= ZONED_DATETIME("2000-01-01T18:00:00Z")]-(o:Person)

エッジ パターンは、2000 年 1 月 1 日以降、完全一致ではなく柔軟な条件を使用して、お互いを知り合っているユーザーを見つけます。

注

エッジ パターン変数は、可変長パターンを使用する場合でも、エッジ パターン述語の個々のエッジに常にバインドされます。 これは、ポストフィルターを実行するためにエッジ グループ リスト変数をアンネストする必要がない場合に役立ちます。 「可変長パターンエッジ変数のバインド」を参照してください。

高度なパターン述語手法:

パターン述語は、クエリの読みやすさを向上させる強力なインライン フィルター機能を提供します。

-- Multiple conditions in node predicates
MATCH (p:Person WHERE p.birthday < 19900101 AND p.gender = 'female')
      -[:workAt]->
      (c:Company WHERE c.name STARTS WITH 'A')

-- Filter on an edge property
MATCH (p1:Person)-[w:workAt WHERE w.workFrom >= 2010]->(c:Company)

-- MATCH WHERE: evaluated after pattern matching
MATCH (p:Person)-[:workAt]->(c:Company)
WHERE p.browserUsed = 'Firefox' AND c.name IS NOT NULL

-- Filter during matching and after
MATCH (p:Person WHERE p.gender = 'male')-[:workAt]->(c:Company)
WHERE p.birthday < 19900101 AND c.url IS NOT NULL

ヒント

どのノードやエッジがマッチに参加できるかを説明する述語をパターン内に保持します。

バインド パス変数

さらに処理したり、完全なパス構造をユーザーに返したりするために、一致したパスをパス変数にバインドすることもできます。

p=(c:Company)<-[:workAt]-(x:Person)-[:knows]-(y:Person)-[:workAt]->(c:Company)

ここで、 p は、指定された順序ですべてのノードとエッジの参照値を含む、完全に一致するパス構造を表すパス値にバインドされます。

バウンドパスはユーザーに返すか、 NODES や EDGESなどの関数でさらに処理されることがあります。

MATCH p=(c:Company)<-[:workAt]-(x:Person)-[:knows]-(y:Person)-[:workAt]->(c:Company)
LET path_edges = edges(p)
RETURN path_edges, size(path_edges) AS num_edges
GROUP BY path_edges

パターンの作成

実際のクエリでは、多くの場合、単純なノード エッジ ノード構造よりも複雑なパターンが必要です。 GQL には、高度なグラフ トラバーサルのパターンを作成するいくつかの方法が用意されています。

パス パターンを作成する

パス パターンは、単純なノードパターンとエッジ パターンを連結して、より長いトラバーサルを作成することによって構成できます。

(:Person)-[:knows]->(:Person)-[:workAt]->(:Company)-[:isLocatedIn]->(:Country)-[:isPartOf]->(:Continent)

このパターンは、仕事仲間の会社がどこにあるかを見つけるために、ソーシャルおよびプロフェッショナルなつながりを通じて人から走査します。

段階的なパターンの構築: パス パターンを段階的に構築することもできます。これによって、複雑なパターンを読みやすく理解しやすくなります。

(:Person)-[:knows]->(p:Person),
(p:Person)-[:workAt]->(c:Company),
(c:Company)-[:isLocatedIn]->(:Country)-[:isPartOf]->(:Continent)

この方法では、同じトラバーサルが論理的な手順に分割され、理解とデバッグが容易になります。

非線形パターンを作成する

パターンの結果の形状は、線形パスである必要はありません。 中心ノードから放射される "星形" パターンのようなより複雑な構造を照合できます。

(p:Person),
(p)-[:studyAt]->(u:University),
(p)-[:workAt]->(c:Company),
(p)-[:likes]-(m)

このパターンでは、教育、雇用、コンテンツの好みと共に、包括的なプロファイル クエリである人物を一度に検索します。

同じ状況のパターン MATCH 変数を共有する必要はありません。 切り離されたパターンは、それらのマッチのデカルト的積を形成します。 パターンが同じグラフ要素をバインドし、結合された組み合わせだけが残るべき場合は変数を再利用します。

制御要素の再利用

GQLは繰り返しノードとエッジを2つのレベルで制御します:

  • マッチモードは、コンマ区切られたパスを含む完全なグラフパターンに適用されます。
  • パスモードは1つのパスに適用されます。

デフォルトのマッチモードは REPEATABLE ELEMENTSです。 これにより、同じ要素のバインディングがグラフパターンの異なる部分で起こり、それぞれのパスモードに依存します。 明示的に書くこともできます:

REPEATABLE ELEMENTS (a)-[e1:knows]->(b), (a)-[e2:knows]->(c)

DIFFERENT EDGESまたはその同義語DIFFERENT RELATIONSHIPSを用いて、完全なグラフパターン全体でエッジの一意性を要求します。 このマッチモードは、パターン内の WALK パスを動作 TRAIL に変化させます。

DIFFERENT EDGES (a)-[e1:knows]->(b), (a)-[e2:knows]->(c)

以下のパスモードは、各パス内の繰り返し要素を制御します:

パス モード 要素の再利用
WALK ノードやエッジは繰り返し存在します。
TRAIL エッジは繰り返しできませんが、ノードは繰り返し可能です。
SIMPLE ノードは繰り返しできませんが、最初と最後のノードが同じであることが許されます。 エッジは繰り返せない。
ACYCLIC ノードは繰り返しられず、最初と最後のノードも含めて。 エッジは繰り返せない。

WALK はデフォルトのパスモードです。 より厳密な要素一意性が必要な場合、別のモードでパスを接頭辞に付けます:

SIMPLEおよびACYCLICにおいて、エッジの一意性はノードの一意性から導かれます。 SIMPLEパスは最初のノードに戻ることで閉じることができますが、それでもエッジを再利用することはできません。

TRAIL (a)-[e1:knows]->(b)-[e2:knows]->(c)-[e3:knows]->(d)

TRAILパターンは、e1、e2、e3が異なるマッチのみを生み出します。 ノードは繰り返し存在するため、経路はエッジを再利用せずにサイクルを形成できます。

どの経路が返されるかを制御する

パスサーチプレフィックスは、パスパターンが返すパスを制御します。 デフォルトの ALL プレフィックスは、パスモードとパターンに一致するすべてのパスを返します。 ALL明示的に書くことができます:

ALL TRAIL (a:Person)-[:knows]->{1,4}(b:Person)

ANY SHORTESTを使って、各入力行から各送信元-宛先ペアに対して最短マッチングパスを1つ返します。

MATCH p = ANY SHORTEST
  (src:Person)-[:knows]->{1,4}(dst:Person)
RETURN src.id AS sourceId, dst.id AS targetId, path_length(p) AS hopCount
ORDER BY sourceId, targetId
LIMIT 100

複数のパスが最短の長さで同点の場合、クエリはそのうちの1つを返しますが、どの同定パスが返されるかは決定論的ではありません。 下限がゼロであれば、ソースノードから自身へのゼロホップパスを返すことができます。

ALL SHORTEST ANYパスサーチはサポートされていません。

述語を経路選択の前後に置く

述語配置は、条件が適格パスを定義するか、パスサーチプレフィックスが選択したパスをフィルタリングするかを決定します。

  • ノードやエッジパターンのインライン WHERE はパターンの一部です。 ALLまたはANY SHORTESTが適用される前に、どの経路が対象となるかを制約します。
  • 完全なMATCHパターンの後の文レベルのWHEREはポストフィルターです。 パスサーチプレフィックスが選択したパスを経て行をフィルタリングします。
  • その後の FILTER 文もパス選択後に行をフィルタリングします。

この区別は特に ANY SHORTESTで重要です。 以下のパターンでは、指定された日付以降に作成された knows 辺のみが最短パスを選択する際に対象となります。

MATCH p = ANY SHORTEST
  (src:Person WHERE src.firstName = 'Alice')
  -[connection:knows
    WHERE connection.creationDate >= ZONED_DATETIME('2020-01-01T00:00:00Z')]->{1,4}
  (dst:Person WHERE dst.firstName = 'Bob')
RETURN p

エッジ条件を後処理フィルターに移すと意味が変わります。 クエリはまずその条件なしの最短経路を選択します。 条件に合わない辺があれば選択されたパスを削除します。代わりにより長いパスを選択するわけではありません。

MATCH p = ANY SHORTEST
  (src:Person WHERE src.firstName = 'Alice')
  -[connections:knows]->{1,4}
  (dst:Person WHERE dst.firstName = 'Bob')
FILTER ALL(connection IN connections
           WHERE connection.creationDate >= ZONED_DATETIME('2020-01-01T00:00:00Z'))
RETURN p

Important

一部の ANY SHORTEST クエリ形状については、Graphは現在パス選択前に文レベルの MATCH ... WHERE 条件を適用できます。 この制限が解決されるまでは、パス適格性にはインライン述語を使用し、選択後フィルタリングには別の FILTER 文を用いてください。 詳細については、現在の制限事項に関する記事を参照してください。

可変長パターンを使用する

可変長パターンは、反復的なパターン仕様を記述することなく、さまざまな長さのパスを見つけることができる強力なコンストラクトです。 階層、ソーシャル ネットワーク、最適なパスの長さが事前にわかっていないその他の構造を走査するために不可欠です。

境界付き可変長パターン

多くの一般的なグラフ クエリでは、同じエッジ パターンを複数回繰り返す必要があります。 次のような詳細なパターンを記述する代わりに、

(:Person)-[:knows]->(:Person)-[:knows]->(:Person)-[:knows]->(:Person)

より簡潔な可変長構文を使用できます。

(:Person)-[:knows]->{3}(:Person)

{3}は、-[:knows]->エッジ パターンを 3 回正確に繰り返す必要があることを指定します。

柔軟な繰り返し範囲: 柔軟性を高めるために、繰り返しの下限と上限の両方を指定できます。

(:Person)-[:knows]->{1, 3}(:Person)

このパターンは、直接のフレンド、フレンドのフレンド、フレンドのフレンドをすべて 1 つのクエリで検索します。

注

下限はゼロでもよい。 ゼロホップマッチはエッジを含まず、両方のエンドポイントノードパターンが同じノードに一致する必要があります。

Example:

(p1:Person)-[:knows]->{0,1}(p2:Person)

このパターンは、 p1 と p2 の両方で各人を0ホップでマッチさせ、接続ペアを1ホップでマッチさせます。

{,n}で下限が指定されていない場合、デフォルトはゼロになります。

複素可変長合成: 可変長パターンは、以下のクエリのように、より大きく複雑なパターンの一部となることがあります。

MATCH (c1:Comment)<-[:likes]-(p1:Person)-[:knows]-(p2:Person)-[:likes]->(c2:Comment),
      (c1:Comment)<-[:replyOf]-{1,3}(m)-[:replyOf]->{1,3}(c2:Comment)
RETURN *
LIMIT 100

このパターンは、知り合い同士が異なるコメントに「いいね」を付けたコメントのペアを見つけ、メッセージ m が1から3つの replyOf 辺の連鎖でつながれています。

可変長パターンのエッジ変数をバインドする

可変長エッジ パターンをバインドすると、参照コンテキストに応じてエッジ変数の値と型が変わります。 この動作を理解することは、可変長の一致を正しく処理するために重要です。

2 つの参照度:

  • 可変長パターン内: グラフ エッジ変数は、一致したパス ("シングルトン参照度" とも呼ばれます) に沿って個々のエッジにバインドされます。
  • 可変長パターンの外側: グラフ エッジ変数は、一致したパス ("グループ参照の次数" とも呼ばれます) に沿ってすべてのエッジのシーケンスにバインドされます。

両方のコンテキストを示す例:

MATCH (:Person)-[e:knows WHERE e.creationDate >= ZONED_DATETIME("2000-01-01T00:00:00Z")]->{1,3}()
RETURN e[0]
LIMIT 100

エッジ変数 e の評価は、次の 2 つのコンテキストで行われます。

  • MATCHステートメント: クエリは、2000 年以降に各フレンドシップが確立されたフレンドのフレンドのチェーンを検索します。 パターン マッチング中、エッジ パターン述語 e.creationDate >= ZONED_DATETIME("2000-01-01T00:00:00Z") は、候補エッジごとに 1 回評価されます。 このコンテキストでは、 e は単一のエッジ参照値にバインドされます。

  • RETURNステートメント: ここでは、eは、一致したチェーン内で発生する順序でエッジ参照値の (グループ) リストにバインドされます。 e[0]の結果は、一致した各チェーンの最初のエッジ参照値です。

水平集約における可変長パターンのエッジ変数:

可変長パターンマッチングで境界付けられた辺変数は可変長パターンの外にあるグループリストであり、水平集約に利用可能です。

MATCH (a:Person)-[e:knows WHERE e.creationDate >= ZONED_DATETIME("2000-01-01T00:00:00Z")]->{1,3}(b)
RETURN a, b, size(e) AS num_edges
LIMIT 100

詳細については、 集計関数を参照してください。

無制限の可変長パターン

最大経路長が不明な場合は、無界量化子を用いましょう:

-- Two or more edges
TRAIL (:Person)-[:knows]->{2,}(:Person)

*ショートカットと+ショートカットは、0回以上および1回以上の繰り返しを指定します。

-- Zero or more edges
ACYCLIC (:Person)-[:knows]->*(:Person)

-- One or more edges
SIMPLE (:Person)-[:knows]->+(:Person)

デフォルトの ALL WALK の組み合わせを持つ無界パターンは、サイクルが無限に多くの一致経路を生み出す可能性があるため却下されます。 TRAIL、SIMPLE、またはACYCLICを使って、エッジやノードの一意性でパスをバウンディングします。 これらのモードは終端を保証しますが、大きなグラフでも多数の経路を生成することがあります。

Important

境界のない ANY SHORTEST WALKで区切られた経路の場合、支援される用途は PATH_LENGTH(path) とそれに並ぶ path IS NULLのみです。 グラフはこの形で完全な経路を具現化しません。 有限上限を用いるか、 TRAIL、 SIMPLE、または ACYCLIC を指定するか、パスを返すか他の方法で使います。