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

Mit den folgenden pfadspezifischen Funktionen können Sie einen Diagrammpfad abfragen. Allgemeine Informationen zu Spanner Graph-Abfragen finden Sie unter Übersicht über Abfragen.

EDGES

Die Funktion EDGES gibt alle Kanten in einem Graphpfad 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

Mit der Funktion PATH_FIRST wird der erste Knoten in einem Diagrammpfad gesucht. 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

Mit der Funktion PATH_LAST wird der letzte Knoten in einem Graphpfad ermittelt. 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. Ausführliche Informationen zur 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 Diagrammpfad 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, einschließlich Pfaden 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 entspricht jedem Pfad zwischen den einzelnen [a, b]-Paaren.

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

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 die Konto-ID 20 zurückgibt, ist möglicherweise zu breit gefasst, da sie mit der Konto-ID 20 beginnt. Um spezifischere Ergebnisse zu erhalten, 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
  • Wenden Sie in Ihrer Anfrage einen IS_ACYCLIC(p)-Filter an.

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 Knotenpunktkonto 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