Mit Pfaden arbeiten

Auf dieser Seite wird beschrieben, wie Sie mit Pfaden in Spanner Graph arbeiten.

In Graphendatenbanken stellt der Datentyp „Graphpfad“ eine Folge von Knoten dar, die mit Kanten verschachtelt sind, und zeigt, wie diese Knoten und Kanten zusammenhängen. Weitere Informationen zum Datentyp „Pfad“ finden Sie unter Datentyp „Graphpfad“.

Mit der Spanner Graph Language (GQL) können Sie Diagrammpfade erstellen und Abfragen für diese Pfade ausführen. In den Beispielen in diesem Dokument wird dasselbe Spanner Graph-Schema verwendet wie auf der Seite Cloud Spanner Graph einrichten und abfragen.

Diagrammpfad erstellen

Sie können einen Pfad im Diagramm erstellen, indem Sie eine Pfadvariable in einem Diagrammmuster oder mit der PATH-Funktion erstellen.

Wir empfehlen, einen Diagrammpfad mit der Pfadvariablen zu erstellen. Das Format zum Erstellen einer Pfadvariablen ist:

MATCH p = PATH_PATTERN

Weitere Informationen finden Sie unter Graph-Muster.

Beispiel

Im folgenden Beispiel werden mit der Abfrage Muster für Geldüberweisungen zwischen Konten in FinGraph gesucht.

GRAPH FinGraph
MATCH p = (src:Account {id: 16})-[t:Transfers]->{2}(dst:Account {id: 7})
RETURN TO_JSON(p) AS full_path;

Ergebnis

full_path
[{"identifier": ..., "properties": {"id": 16, ...}, ...}, {"identifier": ..., "properties": {"amount": 300.0, ...}, ...}, ...]

Das Ergebnis zeigt, dass das Muster Account -> Transfers -> Account in der Datenbank gefunden wurde.

Graphpfad abfragen

Sie können die folgenden pfadspezifischen Funktionen verwenden, um einen Diagrammpfad abzufragen. Allgemeine Informationen zu Spanner Graph-Abfragen finden Sie unter Übersicht über Abfragen.

EDGES

Die Funktion EDGES gibt alle Kanten in einem Diagrammpfad zurück. Eine detaillierte Beschreibung der Semantik finden Sie unter EDGES.

Beispiel

Mit dieser Abfrage wird ein Pfad zwischen zwei Konten gefunden, der über ein mittleres Konto verläuft. Es wird der Betrag der zweiten Transfers-Kante im Pfad zurückgegeben, der zwischen src und mid oder zwischen mid und dst liegen kann.

GRAPH FinGraph
MATCH p = (src:Account {id: 7})-[t1:Transfers]->{1,3}(mid:Account)-[t2:Transfers]->
  {1,3}(dst:Account {id: 16})
LET second_edge = EDGES(p)[1]
RETURN DISTINCT src.id AS src, dst.id AS dst, second_edge.amount AS second_edge_amount;

Ergebnis

src dst second_edge_amount
7 16 300

NODES

Die Funktion NODES gibt alle Knoten in einem Diagrammpfad zurück. Eine detaillierte Beschreibung der Semantik finden Sie unter NODES.

Beispiel

Mit dieser Abfrage wird der Pfad im Diagramm von zwei Transfers ermittelt und dann eine JSON-Liste zurückgegeben, die den Pfad darstellt.

GRAPH FinGraph
MATCH p = (src:Account)-[t:Transfers]->{2}(dst:Account)
RETURN TO_JSON(NODES(p)) AS nodes;

Ergebnis

Knoten
[{"identifier": "...", "properties": {"id": 16}, ...}, {"identifier": "...", "properties": {"id": 20, ...}, ...]

PATH_FIRST

Die Funktion PATH_FIRST sucht den ersten Knoten in einem Diagrammpfad. Eine detaillierte Beschreibung der Semantik finden Sie unter PATH_FIRST.

Beispiel

Mit dieser Abfrage wird der erste Knoten in einem Diagrammpfad mit zwei Transfers ermittelt. Es gibt das Label des Account-Knotens und den Alias des Kontos zurück.

GRAPH FinGraph
MATCH p = -[:Transfers]->{1,3}(dst:Account{id: 7})
RETURN DISTINCT PATH_FIRST(p).id AS can_reach_target;

Ergebnis

can_reach_target
7
16
20

PATH_LAST

Die Funktion PATH_LAST sucht den letzten Knoten in einem Graphpfad. Eine detaillierte Beschreibung der Semantik finden Sie unter PATH_LAST.

Beispiel

Mit dieser Abfrage wird der letzte Knoten in einem Diagrammpfad mit zwei Transfers ermittelt. Es gibt das Label des Account-Knotens und den Alias des Kontos zurück.

GRAPH FinGraph
MATCH p =(start:Account{id: 7})-[:Transfers]->{1,3}
RETURN DISTINCT PATH_LAST(p).id as can_reach_target;

Ergebnis

can_reach_target
7
16
20

PATH_LENGTH

Mit der Funktion PATH_LENGTH wird die Anzahl der Kanten in einem Diagrammpfad ermittelt. Eine detaillierte Beschreibung der Semantik finden Sie unter PATH_LENGTH.

Beispiel

Mit dieser Abfrage wird die Anzahl der Kanten in einem Diagrammpfad ermittelt, der ein bis drei Transfers enthält.

GRAPH FinGraph
MATCH p = (src:Account)-[e:Transfers]->{1,3}(dst:Account)
RETURN PATH_LENGTH(p) AS num_transfers, COUNT(*) AS num_paths;

Ergebnis

num_transfers num_paths
1 5
2 7
3 11

IS_ACYCLIC

Die Funktion IS_ACYCLIC prüft, ob ein Graphpfad sich wiederholende Knoten enthält. Die Funktion gibt TRUE zurück, wenn eine Wiederholung gefunden wird, andernfalls FALSE. Eine detaillierte Beschreibung der Semantik finden Sie unter IS_ACYCLIC.

Beispiel

Mit dieser Abfrage wird geprüft, ob dieser Diagrammpfad sich wiederholende Knoten enthält.

GRAPH FinGraph
MATCH p = (src:Account)-[t:Transfers]->{2}(dst:Account)
RETURN IS_ACYCLIC(p) AS is_acyclic_path,
       ARRAY_TRANSFORM(NODES(p), n->n.id) AS account_ids;

Ergebnis

is_acyclic_path account_ids
TRUE 16,20,7
TRUE 20,7,16
TRUE 20,7,16
FALSE 16,20,16
TRUE 7,16,20
TRUE 7,16,20
FALSE 20,16,20

IS_TRAIL

Die Funktion IS_TRAIL prüft, ob ein Graphpfad sich wiederholende Kanten enthält. Die Funktion gibt TRUE zurück, wenn eine Wiederholung gefunden wird, andernfalls FALSE. Eine detaillierte Beschreibung der Semantik finden Sie unter IS_TRAIL.

Beispiel

Mit dieser Abfrage wird geprüft, ob dieser Diagrammpfad sich wiederholende Kanten enthält.

GRAPH FinGraph
MATCH p = (src:Account)-[t:Transfers]->{3}(dst:Account)
WHERE src.id < dst.id
RETURN IS_TRAIL(p) AS is_trail_path,
       ARRAY_TRANSFORM(t, t->t.id) AS transfer_ids

Ergebnis

is_trail_path transfer_ids
FALSE 16,20,16
TRUE 7,16,20
TRUE 7,16,20

Pfadmodi

In Spanner Graph werden standardmäßig alle Pfade zurückgegeben, auch Pfade mit sich wiederholenden Knoten und Kanten. Sie können die folgenden Pfadmodi verwenden, um Pfade mit sich wiederholenden Knoten und Kanten ein- oder auszuschließen. Eine detaillierte Beschreibung der Semantik finden Sie in der Dokumentation zum Pfadmodus.

WALK

Im Pfadmodus WALK werden alle Pfade zurückgegeben, einschließlich Pfade mit sich wiederholenden Knoten und Kanten. WALK ist der Standardpfadmodus.

Beispiel

Die folgende Abfrage veranschaulicht die Verwendung des Pfadmodus WALK für ein quantifiziertes Pfadmuster. Der erste Pfad in den Ergebnissen hat wiederholte Kanten.

GRAPH FinGraph
MATCH p = WALK (src:Account)-[t:Transfers]->{3}(dst:Account)
WHERE src.id < dst.id
RETURN ARRAY_TRANSFORM(t, t->t.id) AS transfer_ids

Ergebnis

transfer_ids
16,20,16
7,16,20
7,16,20

ACYCLIC

Im Pfadmodus ACYCLIC werden Pfade mit sich wiederholenden Knoten herausgefiltert.

Beispiel

Die folgende Abfrage veranschaulicht die Verwendung des Pfadmodus ACYCLIC für ein quantifiziertes Pfadmuster. Der Pfad mit gleichen src- und dst-Knoten wird herausgefiltert.

GRAPH FinGraph
MATCH p = ACYCLIC (src:Account)-[t:Transfers]->{2}(dst:Account)
RETURN ARRAY_TRANSFORM(NODES(p), n->n.id) AS account_ids

Ergebnis

account_ids
16,20,7
20,7,16
20,7,16
7,16,20
7,16,20

TRAIL

Im Pfadmodus TRAIL werden Pfade mit sich wiederholenden Kanten herausgefiltert.

Beispiel

Die folgende Abfrage veranschaulicht die Verwendung des Pfadmodus TRAIL für ein quantifiziertes Pfadmuster. Pfade mit wiederholten Kanten werden herausgefiltert.

GRAPH FinGraph
MATCH p = TRAIL (src:Account)-[t:Transfers]->{3}(dst:Account)
WHERE src.id < dst.id
RETURN ARRAY_TRANSFORM(t, t->t.id) AS transfer_ids

Ergebnis

transfer_ids
7,16,20
7,16,20

Pfadsuchpräfix

Sie können ein Pfadsuchpräfix verwenden, um ein Pfadmuster so einzuschränken, dass der kürzeste Pfad aus jeder Datenpartition zurückgegeben wird. Eine detaillierte Beschreibung der Semantik finden Sie unter Präfix für die Pfadsuche.

ANY SHORTEST

Das Suchpräfix für den Pfad ANY SHORTEST gibt den kürzesten Pfad (den Pfad mit der geringsten Anzahl von Kanten) zurück, der dem Muster aus jeder Datenpartition entspricht. Wenn es mehrere kürzeste Pfade pro Partition gibt, wird einer davon zurückgegeben.

Beispiel

Die folgende Abfrage findet alle Pfade zwischen den einzelnen Paaren von [a, b].

GRAPH FinGraph
MATCH p = ANY SHORTEST (a:Account {is_blocked:true})-[t:Transfers]->{1,4}(b:Account)
LET total_amount = SUM(t.amount)
RETURN a.id AS account1_id, total_amount, b.id AS account2_id;

Ergebnis

account1_id total_amount account2_id
16 500 16
16 800 7
16 300 20

ANY CHEAPEST

Das Präfix ANY CHEAPEST für die Pfadsuche sorgt dafür, dass für jedes Paar von Quell- und Zielkonten nur ein Pfad mit den geringsten Gesamtkosten für die Berechnung zurückgegeben wird. Der günstigste Pfad ist der mit den niedrigsten Gesamtkosten für die Berechnung, die aus COST-Ausdrücken für Kanten auf dem Pfad berechnet werden. Wenn es mehrere günstigste Pfade pro Partition gibt, wird einer davon zurückgegeben.

Beispiel

Mit der folgenden Abfrage wird einer der günstigsten Pfade zwischen jedem Kontopaar, dargestellt durch a und b, basierend auf dem Überweisungsbetrag ermittelt.

GRAPH FinGraph
MATCH ANY CHEAPEST (a:Account)-[t:Transfers COST t.amount]->{1,3}(b:Account)
LET total_cost = sum(t.amount)
RETURN a.id AS account1_id, b.id AS account2_id, total_cost

Ergebnis

account1_id account2_id total_cost
7 7 900
7 16 100
7 20 400
16 7 800
16 16 500
16 20 300
20 7 500
20 16 200
20 20 500

Konversionsregeln

Weitere Informationen finden Sie unter Konvertierungsregeln für GRAPH_PATH.

Beispiel für einen Anwendungsfall

Im folgenden Beispiel für einen Anwendungsfall sehen Sie, dass alle Konten über ein bis drei Konten weitergeleitet wurden, beginnend mit der Konto-ID 20.

GRAPH FinGraph
MATCH p = (start:Account {id: 20})-[:Transfers]->{1,3}(dst:Account)
RETURN DISTINCT dst.id AS dst;

Ergebnis

dst
7
16
20

Eine Abfrage, die zur Konto-ID 20 zurückkehrt, ist jedoch möglicherweise zu breit gefasst, da sie mit der Konto-ID 20 beginnt. Wenn Sie spezifischere Ergebnisse erhalten möchten, können Sie erzwingen, dass in Ihrer Abfrage nur azyklische Graphpfade ohne sich wiederholende Knoten angezeigt werden. Dazu haben Sie folgende Möglichkeiten:

  • Verwenden Sie MATCH p = ACYCLIC <path_pattern> oder
  • IS_ACYCLIC(p)-Filter in der Abfrage anwenden

In der folgenden Abfrage wird MATCH p = ACYCLIC PATH_PATTERN verwendet:

GRAPH FinGraph
MATCH p = ACYCLIC (start:Account {id: 20})-[:Transfers]->{1,3}(dst:Account)
RETURN DISTINCT dst.id AS dst;

Ergebnis

dst
7
16

Wenn Sie wissen möchten, über welches Konto das Geld zuerst überwiesen wird, können Sie die folgende Abfrage ausführen:

GRAPH FinGraph
MATCH p = ACYCLIC (start:Account {id: 20})(-[:Transfers]->
  (nexts:Account)){1,3}(dst:Account)
RETURN dst.id AS dst, ARRAY_AGG(DISTINCT nexts[0].id) AS unique_starts;

Diese Abfrage ist unkonventionell, da sie eine neue Variable im quantifizierten Pfad mit nexts einführt, um das Ergebnis zu erhalten. Mit Pfadvariablen können Sie die Abfrage vereinfachen:

GRAPH FinGraph
MATCH p = ACYCLIC (start:Account {id: 20})-[:Transfers]->{1,3}(dst:Account)
RETURN dst.id AS dst, ARRAY_AGG(DISTINCT NODES(p)[OFFSET(1)].id) AS unique_starts;

Wenn Sie NODES(p) verwenden, werden alle Knoten auf dem Pfad zurückgegeben. Da das erste Knoten-Konto als start angegeben ist, ist das nächste Konto (beim ersten Offset) das erste Konto, über das Geld überwiesen wird.

Ergebnis

dst unique_starts
7 16, 7

Pfade sind nützlicher, wenn es mehrere quantifizierte Pfade gibt. Sie können eine Einschränkung hinzufügen, dass die Pfade, die über start gefunden werden, die Konto-ID 7 durchlaufen müssen:

GRAPH FinGraph
MATCH p = ACYCLIC (start:Account {id: 20})-[:Transfers]->
  {1,3}(mid:Account {id: 7})-[:Transfers]->{1,3}(dst:Account)
RETURN dst.id AS dst,
  ARRAY_AGG(DISTINCT NODES(p)[OFFSET(1)].id) AS unique_starts;

Obwohl sich die MATCH-Anweisung geändert hat, muss der Rest der Abfrage nicht geändert werden. Ohne Pfadvariablen kann Spanner in einigen Fällen nicht statisch ermitteln, welcher quantifizierte Pfad untersucht werden soll.

Mit einer Pfadvariablen können Sie die Summe aller Übertragungen abrufen:

GRAPH FinGraph
MATCH p = ACYCLIC (start:Account {id: 20})-[:Transfers]->
  {1,3}(mid:Account {id: 7})-[:Transfers]->{1,3}(dst:Account)
LET all_transfers = EDGES(p)
LET transfer_amounts = SUM(all_transfers.amount)
RETURN dst.id AS dst,
  ARRAY_AGG(DISTINCT NODES(p)[OFFSET(1)].id) AS participating_neighbor_nodes, transfer_amounts;

Ergebnis

dst participating_neighbor_nodes transfer_amounts
16 7 600
16 7 800

Nächste Schritte