Cette page explique comment utiliser les chemins de graphe dans Spanner Graph.
Dans les bases de données orientées graphe, le type de données "chemin de graphe" représente une séquence de nœuds entrelacés avec des arêtes et montre comment ces nœuds et arêtes sont liés. Pour en savoir plus sur le type de données "chemin", consultez Type de chemin de graphe.
Le langage Spanner Graph (GQL) vous permet de créer des chemins de graphe et d'effectuer des requêtes sur ceux-ci. Les exemples de ce document utilisent le même schéma Spanner Graph que celui présenté sur la page Configurer et interroger Spanner Graph.
Construire un chemin de graphique
Vous pouvez créer un chemin de graphique en créant une variable de chemin dans un modèle de graphique ou avec la fonction PATH.
Nous vous recommandons de créer un chemin de graphique à l'aide de la variable de chemin d'accès. Le format permettant de créer une variable de chemin d'accès est le suivant :
MATCH p = PATH_PATTERN
Pour en savoir plus, consultez Format de graphique.
Exemple
Dans l'exemple suivant, la requête recherche des schémas de transferts d'argent entre comptes dans FinGraph.
GRAPH FinGraph
MATCH p = (src:Account {id: 16})-[t:Transfers]->{2}(dst:Account {id: 7})
RETURN TO_JSON(p) AS full_path;
Résultat
| full_path |
|---|
| [{"identifier": ..., "properties": {"id": 16, ...}, ...}, {"identifier": ..., "properties": {"amount": 300.0, ...}, ...}, ...] |
Le résultat indique que la requête a trouvé le modèle Account -> Transfers -> Account dans la base de données.
Interroger un chemin de graphique
Vous pouvez utiliser les fonctions spécifiques aux chemins suivantes pour interroger un chemin de graphique. Pour obtenir des informations plus générales sur les requêtes Spanner Graph, consultez Présentation des requêtes.
EDGES
La fonction EDGES renvoie tous les nœuds dans un chemin de graphique. Pour en savoir plus sur la sémantique, consultez EDGES.
Exemple
Cette requête trouve un chemin entre deux comptes qui passe par un compte intermédiaire.
Elle renvoie la quantité du deuxième bord Transfers du chemin, qui peut être comprise entre src et mid ou entre mid et dst.
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;
Résultat
| src | dst | second_edge_amount |
|---|---|---|
| 7 | 16 | 300 |
NODES
La fonction NODES renvoie tous les nœuds d'un chemin de graphique. Pour en savoir plus sur la sémantique, consultez NODES.
Exemple
Cette requête recherche le chemin du graphique de deux transferts, puis renvoie une liste JSON représentant le chemin.
GRAPH FinGraph
MATCH p = (src:Account)-[t:Transfers]->{2}(dst:Account)
RETURN TO_JSON(NODES(p)) AS nodes;
Résultat
| nœuds |
|---|
| [{"identifier": "...", "properties": {"id": 16}, ...}, {"identifier": "...", "properties": {"id": 20, ...}, ...] |
| … |
PATH_FIRST
La fonction PATH_FIRST recherche le premier nœud dans un chemin de graphe. Pour en savoir plus sur la sémantique, consultez PATH_FIRST.
Exemple
Cette requête recherche le premier nœud d'un chemin de graphique de deux transferts. Elle renvoie le libellé du nœud Account et le pseudonyme du compte.
GRAPH FinGraph
MATCH p = -[:Transfers]->{1,3}(dst:Account{id: 7})
RETURN DISTINCT PATH_FIRST(p).id AS can_reach_target;
Résultat
| can_reach_target |
|---|
| 7 |
| 16 |
| 20 |
PATH_LAST
La fonction PATH_LAST trouve le dernier nœud d'un chemin de graphique. Pour en savoir plus sur la sémantique, consultez PATH_LAST.
Exemple
Cette requête recherche le dernier nœud d'un chemin de graphe de deux transferts. Il renvoie le libellé du nœud Account et le pseudo du compte.
GRAPH FinGraph
MATCH p =(start:Account{id: 7})-[:Transfers]->{1,3}
RETURN DISTINCT PATH_LAST(p).id as can_reach_target;
Résultat
| can_reach_target |
|---|
| 7 |
| 16 |
| 20 |
PATH_LENGTH
La fonction PATH_LENGTH trouve le nombre d'arêtes dans un chemin de graphique. Pour en savoir plus sur la sémantique, consultez PATH_LENGTH.
Exemple
Cette requête recherche le nombre d'arêtes dans un chemin de graphe contenant une à trois correspondances.
GRAPH FinGraph
MATCH p = (src:Account)-[e:Transfers]->{1,3}(dst:Account)
RETURN PATH_LENGTH(p) AS num_transfers, COUNT(*) AS num_paths;
Résultat
| num_transfers | num_paths |
|---|---|
| 1 | 5 |
| 2 | 7 |
| 3 | 11 |
IS_ACYCLIC
La fonction IS_ACYCLIC vérifie si un chemin de graphique comporte des nœuds qui se répètent. Elle renvoie TRUE si une répétition est détectée, ou FALSE dans le cas contraire. Pour en savoir plus sur la sémantique, consultez IS_ACYCLIC.
Exemple
Cette requête vérifie si ce chemin de graphique comporte des nœuds qui se répètent.
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;
Résultat
| 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
La fonction IS_TRAIL vérifie si un chemin de graphique comporte des arêtes répétées. Elle renvoie TRUE si une répétition est détectée, ou FALSE dans le cas contraire. Pour en savoir plus sur la sémantique, consultez IS_TRAIL.
Exemple
Cette requête vérifie si ce chemin de graphique comporte des arêtes répétées.
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
Résultat
| is_trail_path | transfer_ids |
|---|---|
| FALSE | 16,20,16 |
| TRUE | 7,16,20 |
| TRUE | 7,16,20 |
Modes de chemin
Dans Spanner Graph, le comportement par défaut consiste à renvoyer tous les chemins, y compris ceux comportant des nœuds et des arêtes répétées. Vous pouvez utiliser les modes de chemin d'accès suivants pour inclure ou exclure les chemins d'accès comportant des nœuds et des arêtes qui se répètent. Pour en savoir plus sur la sémantique, consultez la documentation sur le mode Chemin.
WALK
Le mode de chemin WALK renvoie tous les chemins, y compris ceux avec des nœuds et des arêtes qui se répètent. WALK est le mode de chemin par défaut.
Exemple
La requête suivante montre comment utiliser le mode de chemin WALK sur un motif de chemin quantifié. Le premier chemin des résultats comporte des arêtes répétées.
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
Résultat
| transfer_ids |
|---|
| 16,20,16 |
| 7,16,20 |
| 7,16,20 |
ACYCLIC
Le mode de chemin ACYCLIC filtre les chemins comportant des nœuds répétés.
Exemple
La requête suivante montre comment utiliser le mode de chemin ACYCLIC sur un modèle de chemin quantifié.
Le chemin avec des nœuds src et dst égaux est filtré.
GRAPH FinGraph
MATCH p = ACYCLIC (src:Account)-[t:Transfers]->{2}(dst:Account)
RETURN ARRAY_TRANSFORM(NODES(p), n->n.id) AS account_ids
Résultat
| account_ids |
|---|
| 16,20,7 |
| 20,7,16 |
| 20,7,16 |
| 7,16,20 |
| 7,16,20 |
TRAIL
Le mode de chemin TRAIL filtre les chemins comportant des arêtes répétées.
Exemple
La requête suivante montre comment utiliser le mode de chemin TRAIL sur un modèle de chemin quantifié.
Les chemins comportant des arêtes répétées sont filtrés.
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
Résultat
| transfer_ids |
|---|
| 7,16,20 |
| 7,16,20 |
Préfixe de recherche de chemin
Vous pouvez utiliser un préfixe de recherche de chemin pour limiter un modèle de chemin afin de renvoyer le chemin le plus court à partir de chaque partition de données. Pour en savoir plus sur la sémantique, consultez Préfixe de recherche de chemin d'accès.
ANY SHORTEST
Le préfixe de recherche de chemin d'accès ANY SHORTEST renvoie le chemin d'accès le plus court (celui avec le moins d'arêtes) qui correspond au modèle de chaque partition de données. S'il existe plusieurs chemins les plus courts par partition, renvoie l'un d'eux.
Exemple 1
La requête suivante correspond à n'importe quel chemin le plus court entre chaque paire de [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;
Résultat
| account1_id | total_amount | account2_id |
|---|---|---|
| 16 | 500 | 16 |
| 16 | 800 | 7 |
| 16 | 300 | 20 |
Exemple 2
La requête GQL suivante combine une variable de chemin d'accès avec le préfixe de recherche de chemin d'accès ANY SHORTEST et convertit le chemin d'accès en JSON. Cette méthode est utile pour récupérer un seul objet structuré contenant la séquence complète de nœuds et d'arêtes qui composent le chemin le plus court, au lieu des seuls points de terminaison ou de la longueur du chemin. La requête ne renvoie que le chemin le plus court entre les deux comptes.
GRAPH FinGraph
MATCH p = ANY SHORTEST (a:Account {id: 7})-[:Transfers]->{1,3}(d:Account {id: 20})
RETURN TO_JSON(p) AS results;
Résultat
| résultats |
|---|
| [{"identifier": ..., "properties": {"id": 7, "is_blocked": false, "nick_name": "Vacation Fund"}, ...}, ...] |
ANY CHEAPEST
Le préfixe de recherche de chemin ANY CHEAPEST garantit que, pour chaque paire de comptes source et de destination, la requête ne renvoie qu'un seul chemin avec le coût de calcul total minimal. Le chemin le moins cher est celui dont le coût de calcul total est minimal, calculé à partir des expressions COST sur les arêtes du chemin. Si plusieurs chemins les moins chers existent par partition, la requête en renvoie l'un d'eux.
Exemple
La requête suivante fait correspondre l'un des chemins les moins chers entre chaque paire de comptes, représentés par a et b, en fonction du montant du transfert.
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
Résultat
| 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 |
Règles de conversion
Pour en savoir plus, consultez les règles de conversion GRAPH_PATH.
Exemple de cas d'utilisation
Dans l'exemple de cas d'utilisation suivant, vous constatez que tous les comptes ont été routés via un à trois comptes, à partir de l'ID de compte 20.
GRAPH FinGraph
MATCH p = (start:Account {id: 20})-[:Transfers]->{1,3}(dst:Account)
RETURN DISTINCT dst.id AS dst;
Résultat
| dst |
|---|
| 7 |
| 16 |
| 20 |
Toutefois, une requête qui renvoie à l'ID de compte 20 peut être trop large, car elle commence par l'ID de compte 20. Pour afficher des résultats plus spécifiques, vous pouvez forcer votre requête à n'afficher que les chemins de graphe acycliques sans nœuds répétés.
Pour ce faire, vous pouvez :
- Utilisez
MATCH p = ACYCLIC <path_pattern>; ou - Appliquer un filtre
IS_ACYCLIC(p)dans votre requête
La requête suivante utilise MATCH p = ACYCLIC PATH_PATTERN :
GRAPH FinGraph
MATCH p = ACYCLIC (start:Account {id: 20})-[:Transfers]->{1,3}(dst:Account)
RETURN DISTINCT dst.id AS dst;
Résultat
| dst |
|---|
| 7 |
| 16 |
Si vous souhaitez connaître le premier compte par lequel l'argent est transféré, vous pouvez exécuter la requête suivante :
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;
Cette requête est inhabituelle, car elle introduit une nouvelle variable dans le chemin quantifié à l'aide de nexts pour obtenir le résultat. Les variables de chemin vous permettent de simplifier la requête :
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;
L'utilisation de NODES(p) renvoie tous les nœuds du chemin d'accès. Étant donné que le premier compte de nœud est spécifié comme start, le suivant (au premier décalage) est le premier compte par lequel l'argent est transféré.
Résultat
| dst | unique_starts |
|---|---|
| 7 | 16, 7 |
Les chemins sont plus utiles lorsqu'il existe plusieurs chemins quantifiés. Vous pouvez ajouter une contrainte selon laquelle les chemins trouvés à partir de start doivent passer par l'ID de compte 7 :
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;
Bien que l'instruction MATCH ait changé, le reste de la requête n'a pas besoin de changer. Sans utiliser de variables de chemin d'accès, il existe des cas où Spanner ne peut pas savoir statiquement quel chemin d'accès quantifié inspecter.
À l'aide d'une variable de chemin d'accès, vous pouvez obtenir la somme de tous les transferts :
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;
Résultat
| dst | participating_neighbor_nodes | transfer_amounts |
|---|---|---|
| 16 | 7 | 600 |
| 16 | 7 | 800 |