Mit Pfaden arbeiten

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

In Graphdatenbanken stellt der Datentyp „Graphpfad“ eine Sequenz von Knoten dar, die mit Kanten verschachtelt sind, und zeigt, wie diese Knoten und Kanten miteinander in Beziehung stehen. Weitere Informationen zum Pfaddatentyp finden Sie unter Grafikpfadtyp.

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

Graphpfad erstellen

Sie können einen Graphpfad erstellen, indem Sie eine Pfadvariable in einem Graphmuster oder mit der Funktion PATH erstellen.

Wir empfehlen, einen Graphpfad mithilfe der Pfadvariablen zu erstellen. Das Format zum Erstellen einer Pfadvariablen lautet:

MATCH p = PATH_PATTERN

Weitere Informationen finden Sie unter Graphmuster.

Beispiel

Im folgenden Beispiel werden mit der Abfrage Muster von Überweisungen zwischen Konten innerhalb von FinGraph ermittelt.

GRAPH FinGraph
MATCH p = (src:Account {id: 16})-[t1:Transfers]->(mid:Account)-[t2:Transfers]->
  (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 gibt an, dass die Abfrage das Muster Account -> Transfers -> Account in der Datenbank gefunden hat.

Graphpfad abfragen

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

EDGES

Die Funktion EDGES gibt alle Kanten in einem Graphenpfad zurück. Weitere Informationen zur Semantik finden Sie unter EDGES.

Beispiel

Mit dieser Abfrage wird ein Pfad zwischen zwei Konten gefunden, der über ein Mittelkonto führt. Er gibt den Wert der zweiten Transfers-Kante im Pfad zurück, die sich zwischen src und mid oder zwischen mid und dst befinden 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 Graphenpfad zurück. Weitere Informationen zur Semantik finden Sie unter NODES.

Beispiel

Mit dieser Abfrage wird der Graphpfad von zwei Übergängen ermittelt und dann eine JSON-Liste zurückgegeben, die den Pfad darstellt.

GRAPH FinGraph
MATCH p = (src:Account)-[t1:Transfers]->(mid:Account)-[t2:Transfers]->(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 Graphenpfad. Weitere Informationen zur Semantik finden Sie unter PATH_FIRST.

Beispiel

Mit dieser Abfrage wird der erste Knoten in einem Graphpfad mit zwei Übergängen ermittelt. Es gibt das Label des Knotens Account 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 ermittelt den letzten Knoten in einem Graphpfad. Weitere Informationen zur Semantik finden Sie unter PATH_LAST.

Beispiel

Mit dieser Abfrage wird der letzte Knoten in einem Graphpfad mit zwei Übertragungen gefunden. Es gibt das Label des Knotens Account 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 Graphenpfad ermittelt. Weitere Informationen zur Semantik finden Sie unter PATH_LENGTH.

Beispiel

Mit dieser Abfrage wird die Anzahl der Kanten in einem Graphenpfad ermittelt, der ein bis drei Übergänge 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

Mit der Funktion IS_ACYCLIC wird geprüft, ob ein Graphpfad sich wiederholende Knoten enthält. Wenn eine Wiederholung gefunden wird, wird TRUE zurückgegeben, andernfalls FALSE. Weitere Informationen zur Semantik finden Sie unter IS_ACYCLIC.

Beispiel

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

GRAPH FinGraph
MATCH p = (src:Account)-[t1:Transfers]->(mid:Account)-[t2:Transfers]->(dst:Account)
RETURN IS_ACYCLIC(p) AS is_acyclic_path, src.id AS source_account_id,
  mid.id AS mid_account_id, dst.id AS dst_account_id;

Ergebnis

is_acyclic_path source_account_id mid_account_id dst_account_id
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

Mit der Funktion IS_TRAIL wird geprüft, ob ein Graphpfad sich wiederholende Kanten enthält. Wenn eine Wiederholung gefunden wird, wird TRUE zurückgegeben, andernfalls FALSE. Weitere Informationen zur Semantik finden Sie unter IS_TRAIL.

Beispiel

Mit dieser Abfrage wird geprüft, ob dieser Graphpfad sich wiederholende Kanten hat.

GRAPH FinGraph
MATCH p = (src:Account)-[t1:Transfers]->(mid1:Account)-[t2:Transfers]->
  (mid2:Account)-[t3:Transfers]->(dst:Account)
WHERE src.id < dst.id
RETURN IS_TRAIL(p) AS is_trail_path, t1.id AS t1_id, t2.id AS t2_id, t3.id AS t3_id;

Ergebnis

is_trail_path t1_id t2_id t3_id
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 Pfade mit sich wiederholenden Knoten und Kanten. Mit den folgenden Pfadmodi können Sie Pfade mit sich wiederholenden Knoten und Kanten ein- oder ausschließen. Weitere Informationen zur Semantik finden Sie in der Pathmode-Dokumentation.

WALK

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

Beispiel

In der folgenden Abfrage wird die Verwendung des Pfadmodus WALK für ein nicht quantifiziertes Pfadmuster veranschaulicht. Der erste Pfad in den Ergebnissen verwendet dieselbe Kante für t1 und t3.

GRAPH FinGraph
MATCH p = WALK (src:Account)-[t1:Transfers]->(mid1:Account)-[t2:Transfers]->
  (mid2:Account)-[t3:Transfers]->(dst:Account)
WHERE src.id < dst.id
RETURN t1.id AS transfer1_id, t2.id AS transfer2_id, t3.id AS transfer3_id;

Ergebnis

transfer1_id transfer2_id transfer3_id
16 20 16
7 16 20
7 16 20

ACYCLIC

Im Pfadmodus ACYCLIC werden Pfade mit sich wiederholenden Knoten herausgefiltert.

Beispiel

In der folgenden Abfrage wird die Verwendung des Pfadmodus ACYCLIC für ein nicht quantifiziertes Pfadmuster veranschaulicht. Der Pfad mit den gleichen src- und dst-Knoten wird herausgefiltert.

GRAPH FinGraph
MATCH p = ACYCLIC (src:Account)-[t1:Transfers]->(mid:Account)-[t2:Transfers]->(dst:Account)
RETURN src.id AS account1_id, mid.id AS account2_id, dst.id AS account3_id;

Ergebnis

account1_id account2_id account3_id
20 7 16
20 7 16
7 16 20
7 16 20
16 20 7

TRAIL

Im Pfadmodus TRAIL werden Pfade mit sich wiederholenden Kanten herausgefiltert.

Beispiel

In der folgenden Abfrage wird die Verwendung des Pfadmodus TRAIL für ein nicht quantifiziertes Pfadmuster veranschaulicht. Der Pfad, dessen t1- und t3-Kanten gleich sind, wird herausgefiltert.

GRAPH FinGraph
MATCH p = TRAIL (src:Account)-[t1:Transfers]->(mid1:Account)-[t2:Transfers]->
  (mid2:Account)-[t3:Transfers]->(dst:Account)
RETURN
  t1.id AS transfer1_id, t2.id AS transfer2_id, t3.id AS transfer3_id;

Ergebnis

transfer1_id transfer2_id transfer3_id
16 20 7
16 20 7
20 7 16
20 7 16
7 16 20
7 16 20
7 16 20
7 16 20
20 16 20

Pfadsuchpräfix

Mit einem Pfadsuchpräfix können Sie ein Pfadmuster so einschränken, dass der kürzeste Pfad aus jeder Datenpartition zurückgegeben wird. Ausführliche Informationen zur Semantik finden Sie unter Präfix für die Pfadsuche.

ANY SHORTEST

Das Pfadsuchpräfix ANY SHORTEST gibt den kürzesten Pfad (den Pfad mit der geringsten Anzahl von Kanten) zurück, der mit dem Muster aus jeder Datenpartition übereinstimmt. Wenn es mehr als einen kürzesten Pfad pro Partition gibt, wird einer davon zurückgegeben.

Beispiel

Die folgende Abfrage entspricht jedem Pfad zwischen jedem Paar von [a, b].

GRAPH FinGraph
MATCH p = ANY SHORTEST (a:Account)-[t:Transfers]->{1,4}(b:Account)
WHERE a.is_blocked
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 Anwendungsfallbeispiel sehen Sie, dass alle Konten über ein bis drei Konten von der Konto-ID 20 aus weitergeleitet wurden.

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ückgibt, ist jedoch möglicherweise zu breit, da sie mit der Konto-ID 20 beginnt. Wenn Sie spezifischere Ergebnisse erhalten möchten, können Sie in Ihrer Abfrage festlegen, dass nur azyklische Graphpfade ohne sich wiederholende Knoten angezeigt werden. Dazu haben Sie folgende Möglichkeiten:

  • Verwenden Sie MATCH p = ACYCLIC <path_pattern>.
  • IS_ACYCLIC(p)-Filter in die Abfrage einfügen

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 einführt, um mit nexts 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;

Mit NODES(p) werden alle Knoten entlang des Pfades zurückgegeben. Da das erste Knottenkonto 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 besonders nützlich, wenn es mehrere quantifizierte Pfade gibt. Sie können eine Einschränkung hinzufügen, dass die von start gefundenen Pfade 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;

Auch wenn 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 erkennen, welcher quantifizierte Pfad geprüft werden soll.

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

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