Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Réécriture des requêtes Cypher pour les exécuter dans openCypher sur Neptune
Le langage openCypher est un langage de requête déclaratif pour les graphes de propriétés initialement développé par Neo4j, puis rendu open source en 2015. Il a contribué au projet openCypher
OpenCypher la syntaxe est documentée dans le Cypher Query Language Reference, version 9
Comme openCypher contient un sous-ensemble de la syntaxe et des fonctionnalités du langage de requête Cypher, certains scénarios de migration nécessitent soit de réécrire les requêtes dans des formulaires compatibles avec openCypher, soit d'examiner d'autres méthodes pour obtenir le fonctionnement souhaité.
Cette section contient des recommandations pour gérer les différences courantes, mais elles ne sont en aucun cas exhaustives. Testez minutieusement toute application utilisant ces réécritures pour vous assurer que les résultats sont conformes à vos attentes.
Réécriture des fonctions de prédicat None
, All
et Any
Ces fonctions ne font pas partie de la spécification openCypher. Des résultats comparables peuvent être obtenus dans openCypher à l'aide de la compréhension de liste.
Par exemple, recherchez tous les chemins qui vont d'un nœud Start
au nœud End
, mais aucun trajet n'est autorisé à passer par un nœud dont la propriété de classe correspond à D
:
# Neo4J Cypher code match p=(a:Start)-[:HOP*1..]->(z:End) where none(node IN nodes(p) where node.class ='D') return p # Neptune openCypher code match p=(a:Start)-[:HOP*1..]->(z:End) where size([node IN nodes(p) where node.class = 'D']) = 0 return p
La compréhension de liste peut obtenir ces résultats comme suit :
all => size(list_comprehension(list)) = size(list) any => size(list_comprehension(list)) >= 1 none => size(list_comprehension(list)) = 0
Réécriture de la fonction Cypher reduce()
en openCypher
La fonction reduce()
ne fait pas partie de la spécification openCypher. Elle est souvent utilisée pour créer une agrégation de données à partir d'éléments d'une liste. Dans de nombreux cas, vous pouvez utiliser une combinaison de la compréhension de liste et de la clause UNWIND
pour obtenir des résultats similaires.
Par exemple, la requête Cypher suivante trouve tous les aéroports situés sur des trajets comportant un à trois arrêts entre Anchorage (ANC) et Austin (AUS), et renvoie la distance totale de chaque trajet :
MATCH p=(a:airport {code: 'ANC'})-[r:route*1..3]->(z:airport {code: 'AUS'}) RETURN p, reduce(totalDist=0, r in relationships(p) | totalDist + r.dist) AS totalDist ORDER BY totalDist LIMIT 5
Vous pouvez écrire la même requête en openCypher pour Neptune comme suit :
MATCH p=(a:airport {code: 'ANC'})-[r:route*1..3]->(z:airport {code: 'AUS'}) UNWIND [i in relationships(p) | i.dist] AS di RETURN p, sum(di) AS totalDist ORDER BY totalDist LIMIT 5
Réécriture de la clause Cypher FOREACH en openCypher
La clause FOREACH ne fait pas partie de la spécification openCypher. Elle est souvent utilisée pour mettre à jour les données au milieu d'une requête, souvent à partir d'agrégations ou d'éléments au sein d'un chemin.
À titre d'exemple, recherchez tous les aéroports situés sur un trajet ne comportant pas plus de deux arrêts entre Anchorage (ANC) et Austin (AUS) et définissez la propriété « visited » pour chacun d'eux :
# Neo4J Example MATCH p=(:airport {code: 'ANC'})-[*1..2]->({code: 'AUS'}) FOREACH (n IN nodes(p) | SET n.visited = true) # Neptune openCypher MATCH p=(:airport {code: 'ANC'})-[*1..2]->({code: 'AUS'}) WITH nodes(p) as airports UNWIND airports as a SET a.visited=true
Voici un autre exemple :
# Neo4J Example MATCH p=(start)-[*]->(finish) WHERE start.name = 'A' AND finish.name = 'D' FOREACH (n IN nodes(p) | SET n.marked = true) # Neptune openCypher MATCH p=(start)-[*]->(finish) WHERE start.name = 'A' AND finish.name = 'D' UNWIND nodes(p) AS n SET n.marked = true
Réécriture des procédures Neo4j APOC dans Neptune
Les exemples ci-dessous utilisent openCypher pour remplacer certaines des procédures APOC
Réécriture des procédures apoc.export
Neptune propose un éventail d'options pour les exportations de graphes complets et les exportations basées sur des requêtes dans différents formats de sortie tels que CSV et JSON, à l'aide de l'utilitaire neptune-export
Réécriture des procédures apoc.schema
Neptune n'a pas de schéma, d'index ni de contraintes explicitement définis. De nombreuses procédures apoc.schema
ne sont donc plus nécessaires. Voici quelques exemples :
apoc.schema.assert
apoc.schema.node.constraintExists
apoc.schema.node.indexExists
,apoc.schema.relationship.constraintExists
apoc.schema.relationship.indexExists
apoc.schema.nodes
apoc.schema.relationships
Neptune openCypher prend en charge la récupération de valeurs similaires à celles des procédures, comme indiqué ci-dessous. Toutefois, il peut rencontrer des problèmes de performances sur les graphes de grande taille, car l'analyse d'une grande partie du graphe est nécessaire pour pouvoir renvoyer la réponse.
# openCypher replacement for apoc.schema.properties.distinct MATCH (n:airport) RETURN DISTINCT n.runways
# openCypher replacement for apoc.schema.properties.distinctCount MATCH (n:airport) RETURN DISTINCT n.runways, count(n.runways)
Alternatives aux procédures apoc.do
Ces procédures sont utilisées pour fournir une exécution de requête conditionnelle facile à implémenter à l'aide d'autres clauses openCypher. Dans Neptune, il existe au moins deux manières d'obtenir un comportement similaire :
L'une des solutions consiste à combiner les fonctionnalités de compréhension de liste openCypher avec la clause
UNWIND
.Une autre méthode consiste à utiliser les étapes choose() et coalesce() dans Gremlin.
Des exemples de ces approches sont présentés ci-dessous.
Alternatives à apoc.do.when
# Neo4J Example MATCH (n:airport {region: 'US-AK'}) CALL apoc.do.when( n.runways>=3, 'SET n.is_large_airport=true RETURN n', 'SET n.is_large_airport=false RETURN n', {n:n} ) YIELD value WITH collect(value.n) as airports RETURN size([a in airports where a.is_large_airport]) as large_airport_count, size([a in airports where NOT a.is_large_airport]) as small_airport_count # Neptune openCypher MATCH (n:airport {region: 'US-AK'}) WITH n.region as region, collect(n) as airports WITH [a IN airports where a.runways >= 3] as large_airports, [a IN airports where a.runways < 3] as small_airports, airports UNWIND large_airports as la SET la.is_large_airport=true WITH DISTINCT small_airports, airports UNWIND small_airports as la SET la.small_airports=true WITH DISTINCT airports RETURN size([a in airports where a.is_large_airport]) as large_airport_count, size([a in airports where NOT a.is_large_airport]) as small_airport_count #Neptune Gremlin using choose() g.V(). has('airport', 'region', 'US-AK'). choose( values('runways').is(lt(3)), property(single, 'is_large_airport', false), property(single, 'is_large_airport', true)). fold(). project('large_airport_count', 'small_airport_count'). by(unfold().has('is_large_airport', true).count()). by(unfold().has('is_large_airport', false).count()) #Neptune Gremlin using coalesce() g.V(). has('airport', 'region', 'US-AK'). coalesce( where(values('runways').is(lt(3))). property(single, 'is_large_airport', false), property(single, 'is_large_airport', true)). fold(). project('large_airport_count', 'small_airport_count'). by(unfold().has('is_large_airport', true).count()). by(unfold().has('is_large_airport', false).count())
Alternatives à apoc.do.case
# Neo4J Example MATCH (n:airport {region: 'US-AK'}) CALL apoc.case([ n.runways=1, 'RETURN "Has one runway" as b', n.runways=2, 'RETURN "Has two runways" as b' ], 'RETURN "Has more than 2 runways" as b' ) YIELD value RETURN {type: value.b,airport: n} # Neptune openCypher MATCH (n:airport {region: 'US-AK'}) WITH n.region as region, collect(n) as airports WITH [a IN airports where a.runways =1] as single_runway, [a IN airports where a.runways =2] as double_runway, [a IN airports where a.runways >2] as many_runway UNWIND single_runway as sr WITH {type: "Has one runway",airport: sr} as res, double_runway, many_runway WITH DISTINCT double_runway as double_runway, collect(res) as res, many_runway UNWIND double_runway as dr WITH {type: "Has two runways",airport: dr} as two_runways, res, many_runway WITH collect(two_runways)+res as res, many_runway UNWIND many_runway as mr WITH {type: "Has more than 2 runways",airport: mr} as res2, res, many_runway WITH collect(res2)+res as res UNWIND res as r RETURN r #Neptune Gremlin using choose() g.V(). has('airport', 'region', 'US-AK'). project('type', 'airport'). by( choose(values('runways')). option(1, constant("Has one runway")). option(2, constant("Has two runways")). option(none, constant("Has more than 2 runways"))). by(elementMap()) #Neptune Gremlin using coalesce() g.V(). has('airport', 'region', 'US-AK'). project('type', 'airport'). by( coalesce( has('runways', 1).constant("Has one runway"), has('runways', 2).constant("Has two runways"), constant("Has more than 2 runways"))). by(elementMap())
Alternatives aux propriétés basées sur des listes
Neptune ne prend actuellement pas en charge le stockage des propriétés basées sur des listes. Cependant, des résultats similaires peuvent être obtenus en stockant les valeurs de liste sous forme de chaîne séparée par des virgules, puis en utilisant les fonctions join()
et split()
pour construire et déconstruire la propriété de liste.
Par exemple, si nous voulions enregistrer une liste de balises en tant que propriété, nous pourrions utiliser l'exemple de réécriture qui montre comment récupérer une propriété séparée par des virgules, puis utiliser les fonctions split()
et join()
avec la compréhension de liste pour obtenir des résultats comparables :
# Neo4j Example (In this example, tags is a durable list of string. MATCH (person:person {name: "TeeMan"}) WITH person, [tag in person.tags WHERE NOT (tag IN ['test1', 'test2', 'test3'])] AS newTags SET person.tags = newTags RETURN person # Neptune openCypher MATCH (person:person {name: "TeeMan"}) WITH person, [tag in split(person.tags, ',') WHERE NOT (tag IN ['test1', 'test2', 'test3'])] AS newTags SET person.tags = join(newTags,',') RETURN person
Réécriture des sous-requêtes CALL
CALL
Les sous-requêtes Neptune ne prennent pas en charge la syntaxe CALL (friend) { ... }
permettant d'importer des variables dans le champ d'application de la sous-requête (dans cet friend
exemple). Veuillez utiliser la WITH
clause contenue dans la sous-requête pour la même chose, par exemple, CALL { WITH friend ... }
Les CALL
sous-requêtes facultatives ne sont pas prises en charge pour le moment.
Autres différences entre Neptune openCypher et Cypher
Neptune prend uniquement en charge les connexions TCP pour le protocole Bolt. WebSocketsles connexions pour Bolt ne sont pas prises en charge.
Neptune openCypher supprime les espaces tels que définis par Unicode dans les fonctions
trim()
,ltrim()
etrtrim()
.Dans Neptune openCypher,
tostring(
double)
ne passe pas automatiquement en notation E pour les grandes valeurs du double.