Umschreiben von Cypher-Abfragen zur Ausführung in openCypher auf Neptune - Amazon Neptune

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Umschreiben von Cypher-Abfragen zur Ausführung in openCypher auf Neptune

openCypher ist eine deklarative Abfragesprache für Eigenschaftsdiagramme. Ursprünglich von Neo4j entwickelt, wurde sie 2015 als Open-Source-Software veröffentlicht und ist unter einer Apache-2-Open-Source-Lizenz für das openCypher-Projekt verfügbar. Wir bei AWS sind davon überzeugt, dass Open Source für alle gut ist, und setzen uns dafür ein, sowohl unseren Kunden den Wert von Open Source näherzubringen als auch Open-Source-Communitys die operative Exzellenz von AWS zu bieten.

Die OpenCypher-Syntax ist in der Cypher Query Language Reference, Version 9 dokumentiert.

Da OpenCypher eine Teilmenge der Syntax und Features der Cypher-Abfragesprache enthält, erfordern einige Migrationsszenarien entweder das Umschreiben von Abfragen in mit OpenCypher kompatible Form oder die Prüfung alternativer Methoden, um die gewünschte Funktionalität zu erreichen.

Dieser Abschnitt enthält Empfehlungen zum Umgang mit häufigen Unterschieden, die jedoch keineswegs erschöpfend sind. Sie sollten jede Anwendung, die diese Umschreibungen verwendet, gründlich testen, um sicherzustellen, dass die Ergebnisse Ihren Erwartungen entsprechen.

Umschreiben von None-, All- und Any-Prädikatfunktionen

Diese Funktionen sind nicht Teil der openCypher-Spezifikation. Vergleichbare Ergebnisse können mit List Comprehension in openCypher erzielt werden.

Finden Sie zum Beispiel alle Pfade, die von Knoten Start zu Knoten End führen, wobei aber kein Pfad einen Knoten passieren darf, dessen Klasseneigenschaft D ist:

# 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

List Comprehension kann diese Ergebnisse können wie folgt erreichen:

all => size(list_comprehension(list)) = size(list) any => size(list_comprehension(list)) >= 1 none => size(list_comprehension(list)) = 0

Umschreiben der Cypher-Funktion reduce() zu openCypher

Die reduce()-Funktion ist nicht Teil der openCypher-Spezifikation. Sie wird häufig verwendet, um eine Aggregierung von Daten aus Elementen innerhalb einer Liste zu erstellen. In vielen Fällen können Sie eine Kombination aus List Comprehension und der UNWIND-Klausel verwenden, um ähnliche Ergebnisse zu erreichen.

Die folgende Cypher-Abfrage findet beispielsweise alle Flughäfen auf Wegen mit einer bis drei Stopps zwischen Anchorage (ANC) und Austin (AUS) und gibt die Gesamtentfernung für jeden Pfad zurück:

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

Sie können dieselbe Abfrage in openCypher für Neptune wie folgt schreiben:

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

Umschreiben der Cypher-Klausel FOREACH zu openCypher

Die FOREACH–Klausel ist nicht Teil der openCypher-Spezifikation. Sie wird häufig verwendet, um Daten während einer Abfrage zu aktualisieren, oft anhand von Aggregierungen oder Elementen innerhalb eines Pfads.

Finden Sie als Beispiel für einen Pfad nach allen Flughäfen auf einem Pfad mit nicht mehr als zwei Stopps zwischen Anchorage (ANC) und Austin (AUS) und legen Sie für jeden von ihnen die Eigenschaft „besucht“ fest:

# 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

Ein weiteres Beispiel ist:

# 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

Umschreiben der Neo4j-APOC-Prozeduren zu Neptune

In den folgenden Beispielen wird openCypher verwendet, um einige der am häufigsten verwendeten APOC-Prozeduren zu ersetzen. Diese Beispiele dienen nur als Referenz und sollen einige Vorschläge zum Umgang mit gängigen Szenarien geben. In der Praxis ist jede Anwendung anders und Sie müssen Ihre eigenen Strategien entwickeln, um alle Funktionen bereitzustellen, die Sie benötigen.

Umschreiben von apoc.export-Verfahren

Neptune bietet mithilfe des Neptune-Export-Dienstprogramms eine Reihe von Optionen sowohl für vollständige Graph- als auch für abfragebasierte Exporte in verschiedenen Ausgabeformaten wie CSV und JSON (siehe Exportieren von Daten aus einem Neptune-DB-Cluster).

Umschreiben von apoc.schema-Verfahren

Neptune hat kein explizit definiertes Schema, keine Indizes oder Einschränkungen, so dass viele apoc.schema-Prozeduren nicht mehr erforderlich sind. Beispiele sind:

  • 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 unterstützt das Abrufen ähnlicher Werte wie die Prozeduren, wie unten gezeigt, kann jedoch bei größeren Graphen zu Leistungsproblemen führen, da dafür ein großer Teil des Graphen gescannt werden muss, um die Antwort zurückzugeben.

# 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)

Alternativen zu apoc.do-Prozeduren

Diese Prozeduren werden verwendet, um eine bedingte Abfrageausführung zu ermöglichen, die mit anderen OpenCypher-Klauseln einfach zu implementieren ist. In Neptune gibt es mindestens zwei Möglichkeiten, ein ähnliches Verhalten zu erreichen:

  • Eine Möglichkeit besteht darin, die Listenverständnisfunktionen von OpenCypher mit der UNWIND-Klausel zu kombinieren.

  • Eine andere Möglichkeit besteht darin, die Schritte choose() und coalesce() in Gremlin zu verwenden.

Beispiele für diese Vorgehensweisen sind unten aufgeführt.

Alternativen zu 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())

Alternativen zu apoc.do.when

# 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())

Alternativen zu listenbasierten Eigenschaften

Neptune unterstützt derzeit nicht das Speichern von auf Listen basierenden Eigenschaften. Ähnliche Ergebnisse können jedoch erzielt werden, wenn Listenwerte als kommagetrennte Zeichenfolge gespeichert und dann die Listeneigenschaft mithilfe der Funktionen join() und split() konstruiert und dekonstruiert wird.

Wenn wir beispielsweise eine Liste von Tags als Eigenschaft speichern möchten, könnten wir die Beispiel-Umschreibung verwenden, die zeigt, wie eine durch Kommata getrennte Eigenschaft abgerufen wird, und dann die Funktionen split() und join() mit List Comprehension verwenden, um vergleichbare Ergebnisse zu erzielen:

# 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