Vue d’ensemble
Un modèle de chemin quantifié construit un chemin de longueur variable, où soit le chemin entier, soit un segment de celui-ci est répété un nombre spécifié de fois. Un modèle de chemin quantifié peut être formé en appliquant un quantificateur soit à un modèle d'edge soit à un modèle de chemin parenthétisé.
<quantified path pattern> ::= <quantified edges> | <quantified paths>
<quantified edges> ::= <edge pattern> <quantifier>
<quantified paths> ::= <parenthesized path pattern> <quantifier>
Dans la mise en œuvre, un modèle de chemin quantifié doit être concaténé avec d'autres facteurs de chemin, explicitement ou implicitement, à l'aide d'un modèle de node. Référez-vous aux exemples pour plus de clarification.
Quantificateurs
Un quantificateur est écrit en postfix soit sur un modèle d'edge soit sur un modèle de chemin parenthétisé.
Quantificateur |
Description |
---|---|
{m,n} |
Entre m et n répétitions |
{m} |
Exactement m répétitions |
{m,} |
m ou plus de répétitions |
{,n} |
Entre 0 et n répétitions |
* |
Entre 0 et plus de répétitions |
+ |
Entre 1 et plus de répétitions |
Lorsque la répétition de 0
est indiquée, un chemin (ou sous-chemin) sans edges qui ne contient que le node initial sera inclus dans les correspondances.
Des restrictions syntaxiques sont mises en place pour éviter les boucles infinies, ce qui pourrait se produire lorsqu'un quantificateur non borné est utilisé pour correspondre à un graph qui contient des cycles.
Edges Quantifiés
Les edges quantifiés sont construits par un modèle d'edge suivi d'un quantificateur qui spécifie combien de fois l'edge se répète. Notez que le quantificateur peut être appliqué à la fois aux modèles d'edge complets et abrégés.
Cette expression de modèle de chemin équivaut à :
Les edges répétés sont implicitement connectés par des modèles de node vides.
Exemple de Graph
Les exemples suivants sont exécutés sur ce graph :
Pour créer ce graph, exécutez la requête suivante sur un graph vide :
INSERT (purplechalk:User {_id: "U01", name: "purplechalk"}),
(mochaeach:User {_id: "U02", name: "mochaeach"}),
(rowlock:User {_id: "U03", name: "rowlock"}),
(quasar92:User {_id: "U04", name: "Quasar92"}),
(velvet:User {_id: "U05", name: "Velvet"}),
(brainy:User {_id: "U06", name: "Brainy"}),
(quickfox:User {_id: "U07", name: "Quickfox"}),
(inception:Movie {_id: "M01", name: "Inception"}),
(purplechalk)-[:Follows]->(mochaeach),
(mochaeach)-[:Follows]->(rowlock),
(rowlock)-[:Follows]->(quasar92),
(quasar92)-[:Follows]->(velvet),
(brainy)-[:Follows]->(mochaeach),
(mochaeach)-[:Likes]->(inception),
(quickfox)-[:Likes]->(inception)
Limite Fixe Inférieure et Supérieure
Obtient les utilisateurs que Brainy
peut atteindre par 1 à 3 edges sortants étiquetés Follows
:
MATCH (:User {name: 'Brainy'})-[:Follows]->{1,3}(u:User)
RETURN collect_list(u.name) AS names
Résultat :
names |
---|
["mochaeach", "rowlock", "Quasar92"] |
Longueur Fixe
Obtient les utilisateurs que Brainy
peut atteindre par exactement 2 edges sortants étiquetés Follows
:
MATCH (:User {name: 'Brainy'})-[:Follows]->{2}(u:User)
RETURN collect_list(u.name) AS names
Résultat :
names |
---|
["rowlock"] |
Limite Fixe Inférieure
Obtient les utilisateurs que Brainy
peut atteindre par 2 edges ou plus étiquetés Follows
:
MATCH (:User {name: 'Brainy'})-[:Follows]-{2,}(u:User)
RETURN collect_list(u.name) AS names
Résultat :
names |
---|
["rowlock", "purplechalk", "Quasar92", "Velvet"] |
Obtient les utilisateurs que Brainy
peut atteindre par 0 edges sortants ou plus étiquetés Follows
:
MATCH (:User {name: 'Brainy'})-[:Follows]->*(u:User)
RETURN collect_list(u.name) AS names
Résultat :
names |
---|
["Brainy", "mochaeach", "rowlock", "Quasar92", "Velvet"] |
Obtient les utilisateurs que Brainy
peut atteindre par 1 edge sortant ou plus étiquetés Follows
:
MATCH (:User {name: 'Brainy'})-[:Follows]->+(u:User)
RETURN collect_list(u.name) AS names
Résultat :
names |
---|
["mochaeach", "rowlock", "Quasar92", "Velvet"] |
Limite Fixe Supérieure
Obtient les utilisateurs que Brainy
peut atteindre par 0 à 2 edges étiquetés Follows
:
MATCH (:User {name: 'Brainy'})-[:Follows]-{,2}(u:User)
RETURN collect_list(u.name) AS names
Résultat :
names |
---|
["Brainy", "mochaeach", "rowlock", "purplechalk"] |
Edges Abbrégés Quantifiés
Avec un modèle d'edge abrégé, il n'y a pas de restrictions d'étiquette et de propriété sur l'edge. L'exemple suivant obtient les utilisateurs que Brainy
peut atteindre par 1 à 2 edges :
MATCH (:User {name: 'Brainy'})-{1,2}(u:User)
RETURN collect_list(u.name) AS names
Résultat :
names |
---|
["mochaeach", "rowlock", "purplechalk", "QuickFox"] |
Chemins Quantifiés
Les chemins quantifiés sont construits par un modèle de chemin parenthétisé suivi d'un quantificateur qui spécifie combien de fois le chemin se répète.
Cette expression de modèle de chemin équivaut à :
À la transition entre les groupes, deux modèles de node sont concaténés consécutivement. Ils sont combinés en un seul modèle de node avec toutes les conditions de filtrage fusionnées de manière conjonctive. Dans cet exemple, cela est simple puisque le seul filtrage appliqué est l'étiquette User
:
Avec cela, ce qui précède est simplifié à :
Exemple de Graph
Les exemples suivants sont exécutés sur ce graph :
Pour créer ce graph, exécutez la requête suivante sur un graph vide :
INSERT (jack:User {_id: "U01", name: "Jack"}),
(mike:User {_id: "U02", name: "Mike"}),
(c1:Device {_id: "Comp1"}),
(c2:Device {_id: "Comp2"}),
(c3:Device {_id: "Comp3"}),
(c4:Device {_id: "Comp4"}),
(jack)-[:Owns]->(c1),
(mike)-[:Owns]->(c4),
(c1)-[:Flows {packets: 20}]->(c2),
(c1)-[:Flows {packets: 30}]->(c4),
(c2)-[:Flows {packets: 34}]->(c3),
(c2)-[:Flows {packets: 12}]->(c4),
(c3)-[:Flows {packets: 74}]->(c4)
Limite Fixe Inférieure et Supérieure
Obtient les chemins de 1 à 3 flux de données sortants depuis l'appareil possédé par Jack
vers l'appareil possédé par Mike
, où chaque flux de données a plus de 15 paquets :
MATCH p = (:User {name: 'Jack'})-[:Owns]->()
((:Device)-[f:Flows WHERE f.packets > 15]->(:Device)){1,3}
()<-[:Owns]-(:User {name: 'Mike'})
RETURN p
Résultat :
p |
---|
(:User {_id:"U01", name: "Jack"})-[:Owns]->(:Device {_id: "Comp1"})-[:Flows {packets: 30}]->(:Device {_id: "Comp4"})<-[:Owns]-(:User {_id: "U02", name: "Mike"}) |
(:User {_id: "U01", name: "Jack"})-[:Owns]->(:Device {_id: "Comp1"})-[:Flows {packets: 20}]->(:Device {_id: "Comp2"})-[:Flows {packets: 34}]->(:Device {_id: "Comp3"})-[:Flows {packets: 74}]->(:Device {_id: "Comp4"})<-[:Owns]-(:User {_id: "U02", name: "Mike"}) |
Longueur Fixe
Obtient les chemins de 3 flux de données sortants depuis l'appareil possédé par Jack
vers l'appareil possédé par Mike
, où chaque flux de données a plus de 15 paquets :
MATCH p = (:User {name: 'Jack'})-[:Owns]->()
((:Device)-[f:Flows WHERE f.packets > 15]->(:Device)){3}
()<-[:Owns]-(:User {name: 'Mike'})
RETURN p
Résultat :
p |
---|
(:User {_id: "U01", name: "Jack"})-[:Owns]->(:Device {_id: "Comp1"})-[:Flows {packets: 20}]->(:Device {_id: "Comp2"})-[:Flows {packets: 34}]->(:Device {_id: "Comp3"})-[:Flows {packets: 74}]->(:Device {_id: "Comp4"})<-[:Owns]-(:User {_id: "U02", name: "Mike"}) |
Limite Fixe Inférieure
Obtient les chemins de 2 flux de données sortants ou plus depuis l'appareil possédé par Jack
vers l'appareil possédé par Mike
, où chaque flux de données a plus de 15 paquets :
MATCH p = (:User {name: 'Jack'})-[:Owns]->()
((:Device)-[f:Flows WHERE f.packets > 15]->(:Device)){2,}
()<-[:Owns]-(:User {name: 'Mike'})
RETURN p
Résultat :
p |
---|
(:User {_id: "U01", name: "Jack"})-[:Owns]->(:Device {_id: "Comp1"})-[:Flows {packets: 20}]->(:Device {_id: "Comp2"})-[:Flows {packets: 34}]->(:Device {_id: "Comp3"})-[:Flows {packets: 74}]->(:Device {_id: "Comp4"})<-[:Owns]-(:User {_id: "U02", name: "Mike"}) |
Obtient les chemins de 0 flux de données sortants ou plus depuis l'appareil possédé par Jack
vers l'appareil possédé par Mike
, où chaque flux de données a plus de 15 paquets :
MATCH p = (:User {name: 'Jack'})-[:Owns]->()
((:Device)-[f:Flows WHERE f.packets > 15]->(:Device))*
()<-[:Owns]-(:User {name: 'Mike'})
RETURN p
Résultat :
p |
---|
(:User {_id: "U01", name: "Jack"})-[:Owns]->(:Device {_id: "Comp1"})-[:Flows {packets: 30}]->(:Device {_id: "Comp4"})<-[:Owns]-(:User {_id: "U02", name: "Mike"}) |
(:User {_id: "U01", name: "Jack"})-[:Owns]->(:Device {_id: "Comp1"})-[:Flows {packets: 20}]->(:Device {_id: "Comp2"})-[:Flows {packets: 34}]->(:Device {_id: "Comp3"})-[:Flows {packets: 74}]->(:Device {_id: "Comp4"})<-[:Owns]-(:User {_id: "U02", name: "Mike"}) |
Obtient les chemins de 1 flux de données sortants ou plus depuis l'appareil possédé par Jack
vers l'appareil possédé par Mike
, où chaque flux de données a plus de 15 paquets :
MATCH p = (:User {name: 'Jack'})-[:Owns]->()
((:Device)-[f:Flows WHERE f.packets > 15]->(:Device))+
()<-[:Owns]-(:User {name: 'Mike'})
RETURN p
Résultat :
p |
---|
(:User {_id: "U01", name: "Jack"})-[:Owns]->(:Device {_id: "Comp1"})-[:Flows {packets: 30}]->(:Device {_id: "Comp4"})<-[:Owns]-(:User {_id: "U02", name: "Mike"}) |
(:User {_id: "U01", name: "Jack"})-[:Owns]->(:Device {_id: "Comp1"})-[:Flows {packets: 20}]->(:Device {_id: "Comp2"})-[:Flows {packets: 34}]->(:Device {_id: "Comp3"})-[:Flows {packets: 74}]->(:Device {_id: "Comp4"})<-[:Owns]-(:User {_id: "U02", name: "Mike"}) |
Limite Fixe Supérieure
Obtient les chemins de 0 à 2 flux de données sortants depuis l'appareil possédé par Jack
vers l'appareil possédé par Mike
, où chaque flux de données a plus de 15 paquets :
MATCH p = (:User {name: 'Jack'})-[:Owns]->()
((:Device)-[f:Flows WHERE f.packets > 15]->(:Device)){,2}
()<-[:Owns]-(:User {name: 'Mike'})
RETURN p
Résultat :
p |
---|
(:User {_id: "U01", name: "Jack"})-[:Owns]->(:Device {_id: "Comp1"})-[:Flows {packets: 30}]->(:Device {_id: "Comp4"})<-[:Owns]-(:User {_id: "U02", name: "Mike"}) |
Degré de Référence des Variables d'Élément
Si une variable d'élément est déclarée dans un modèle de chemin quantifié, elle peut alors se lier à plus d'un élément de graph. Les références à la variable d'élément sont interprétées de manière contextuelle.
Degré de Référence Singleton
Cette fonctionnalité n'est pas encore supportée.
Si la référence se produit à l'intérieur du modèle de chemin quantifié, alors la référence a un degré de référence singleton et fait référence au plus à un élément de graph.
MATCH p = ((a)-[]->(b) WHERE a.age < b.age){1,2}
RETURN p
Résultat :
p |
---|
(:User {_id: "U01", name: "rowlock", age: 24})-[:Follows {score: 2}]->(:User {_id: "U02", name: "Quasar92", age: 29}) |
(:User {_id: "U02", name: "Quasar92", age: 29})-[:Follows {score: 3}]->(:User {_id: "U03", name: "claire", age: 35}) |
(:User {_id: "U01", name: "rowlock", age: 24})-[:Follows {score: 2}]->(:User {_id: "U02", name: "Quasar92", age: 29})-[:Follows {score: 3}]->(:User {_id: "U03", name: "claire", age: 35}) |
Dans cette requête, a
et b
sont des singletons qui représentent des nodes individuels. La condition a.age < b.age
est évaluée pour chaque paire de nodes a
et b
à mesure que le chemin est apparié.
Degré de Référence de Groupe
Si la référence se produit à l'extérieur du modèle de chemin quantifié, alors la référence a un degré de référence de groupe et fait référence à la liste complète des éléments du graph. Dans cette circonstance, la variable d'élément est considérée comme une variable de groupe.
MATCH p = ((a)-[]->(b)){1,2}
RETURN p, a, b
Résultat :
p |
a | b |
---|---|---|
(:User {_id: "U01", name: "rowlock", age: 24})-[:Follows {score: 2}]->(:User {_id: "U02", name: "Quasar92", age: 29}) | [(:User {_id: "U01", name: "rowlock", age: 24})] | [(:User {_id: "U02", name: "Quasar92", age: 29})] |
(:User {_id: "U02", name: "Quasar92", age: 29})-[:Follows {score: 3}]->(:User {_id: "U03", name: "claire", age: 35}) | [(:User {_id: "U02", name: "Quasar92", age: 29})] | [(:User {_id: "U03", name: "claire", age: 35})] |
(:User {_id: "U01", name: "rowlock", age: 24})-[:Follows {score: 2}]->(:User {_id: "U02", name: "Quasar92", age: 29})-[:Follows {score: 3}]->(:User {_id: "U03", name: "claire", age: 35}) | [(:User {_id: "U01", name: "rowlock", age: 24}), (:User {_id: "U02", name: "Quasar92", age: 29})] | [(:User {_id: "U02", name: "Quasar92", age: 29}), (:User {_id: "U03", name: "claire", age: 35})] |
Les variables a
et b
sont exposées comme variables de groupe dans l'instruction
RETURN
. Chacune d'elles représente une liste de nodes rencontrés le long des chemins appariés, plutôt qu'un seul node.
La requête suivante déclenche une erreur de syntaxe puisqu'elle traite a
et b
comme des variables singleton en dehors d'un modèle de chemin quantifié :
MATCH p = ((a)-[]->(b)){1,2}
WHERE a.age < b.age
RETURN p
La fonctionnalité d'agrégation horizontale n'est pas encore supportée.
Les variables de groupe peuvent être utilisées pour agréger des données le long des chemins ou edges quantifiés, ce qui est l'agrégation horizontale.
MATCH p = ()-[e]->{1,2}()
WHERE sum(e.score) > 2
RETURN p, collect_list(e.score) AS scores
Résultat :
p |
scores |
---|---|
(:User {_id: "U02", name: "Quasar92", age: 29})-[:Follows {score: 3}]->(:User {_id: "U03", name: "claire", age: 35}) | [3] |
(:User {_id: "U01", name: "rowlock", age: 24})-[:Follows {score: 2}]->(:User {_id: "U02", name: "Quasar92", age: 29})-[:Follows {score: 3}]->(:User {_id: "U03", name: "claire", age: 35}) | [2, 3] |