Monday, February 9, 2026

Validate Neo4j Cypher queries for Amazon Neptune migration


When migrating from Neo4j to Amazon Neptune, it’s best to guarantee Cypher question compatibility is maintained. The Amazon Neptune openCypher implementation usually helps the clauses, operators, expressions, and features outlined within the openCypher specification, however with essential limitations and variations that require cautious consideration. The migration course of requires you to systematically analyze present queries to determine Neo4j-specific syntax, features, and patterns that that you must rework to adjust to Neptune’s specs in order that your graph database purposes perform appropriately within the Amazon Net Companies (AWS) surroundings.

For detailed steerage on migrating a Neo4j graph database to a Neptune database, see Automate your Neo4j to Amazon Neptune migration utilizing the neo4j-to-neptune utility, which helps you streamline you migration course of by offering versatile choices for each absolutely automated and step-by-step approaches.

On this submit, we present you the right way to validate Neo4j Cypher queries earlier than migrating to Neptune utilizing the openCypher Compatibility Checker instrument. You should use this instrument to determine compatibility points early in your migration course of, lowering migration effort and time.

Resolution overview

The openCypher Compatibility Checker instrument offers detailed experiences highlighting particular areas of concern, resembling unsupported features, syntax variations, and Neo4j-specific options that want different implementations in Neptune. The instrument can detect frequent conversion challenges, together with variations in string matching features, aggregation strategies, and sample matching syntax, providing options alternate options which are suitable with Neptune.

While you encounter Neo4j-specific features resembling APOC procedures or customized plugins, the instrument flags these cases and might advocate equal Neptune features or different approaches to attain the identical performance. It generates complete experiences that element which elements of your queries may be immediately transformed, which require modification, and which could want full restructuring. Via this systematic method, you’ll be able to prioritize your conversion efforts and estimate the work required for a profitable migration.The answer structure is easy. It doesn’t require an AWS surroundings; the instrument may be downloaded from GitHub and used in your consumer machine or desktop. The next diagram reveals the workflow of the method of utilizing the openCypher Compatibility Checker instrument.

The openCypher Compatibility Checker instrument processes a JSON file of Cypher queries, evaluates their compatibility with the openCypher specification, and generates a JSON output containing both robotically transformed openCypher queries or really useful alternate options for queries that require guide adjustment.

Stipulations

To implement the answer, that you must have the next conditions in place:

Methods to use the instrument

The openCypher Compatibility Checker expects a JSON enter file with a particular construction:

{
"targetSystem": "na|ndb",
  "queries": [
     {
     "id": 1,
     "query": "_query_text_"
     }
 ]
 } 

The JSON object has two major fields. The targetSystem subject specifies the goal database system na(Neptune Analytics) or ndb (Neptune database), whereas the queries array accommodates a number of question objects to be processed in a single batch. Every question object contains an id subject, a singular numeric identifier that distinguishes every question, and a question subject containing the precise Cypher question textual content to be analyzed and transformed. You may embrace as many queries as wanted within the array, with every requiring a singular ID to trace outcomes and determine which queries want consideration. The instrument processes all queries within the batch and returns outcomes mapped to their corresponding IDs, so you’ll be able to analyze a number of queries effectively in a single execution.

The next instance JSON construction defines a batch of Cypher queries for compatibility checking. The instrument processes two queries: one retrieving Individual nodes (id: 1) and one other discovering Person-FOLLOWS relationships (id: 2), returning compatibility evaluation and any essential transformations for every.

{
    "targetSystem": "na",
    "queries": [
        {
            "id": 1,
            "query": "MATCH (n:Person) RETURN n"
        },
        {
            "id": 2,
            "query": "MATCH (n:User)-[:FOLLOWS]->(m) RETURN n,m"
        }
    ]
}

Instance enter: Pattern Cypher queries for compatibility

To reveal the working of the openCypher Compatibility Checker instrument, I’ll use the next instance file, which accommodates a couple of cypher queries:

{
  "targetSystem": "NA",
  "queries": [
    {
      "id": 1,
      "query": "match p=(a:Start)-[:HOP*1..]->(z:Finish) the place none(node IN nodes(p) the place node.class="D") return p"
    },
    {
      "id": 2,
      "question": "MATCH p=(a:airport {code: 'ANC'})-[r:route*1..3]->(z:airport {code: 'AUS'}) RETURN p, scale back(totalDist=0, r in relationships(p) | totalDist + r.dist) AS totalDist ORDER BY totalDist LIMIT 5"
    },
    {
      "id": 3,
      "question": "MATCH p=(:airport {code: 'ANC'})-[*1..2]->({code: 'AUS'}) FOREACH (n IN nodes(p) | SET n.visited = true)"
    },
     SET n.marked = true)"
    ,
    {
      "id": 5,
      "question": "MATCH (n:airport {area: '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 worth WITH gather(worth.n) as airports RETURN measurement([a in airports where a.is_large_airport]) as large_airport_count, measurement([a in airports where NOT a.is_large_airport]) as small_airport_count"
    },
    {
      "id": 6,
      "question": "MATCH (n:airport {area: '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 greater than 2 runways" as b') YIELD worth  RETURN {sort: worth.b,airport: n}"
    }
  ]
}
 

The instance accommodates six queries with various compatibility ranges for the Neptune openCypher format.

Question ID 1 makes use of the none() predicate perform to filter paths. This question is supported however requires minor modification as defined within the Neptune documentation on rewriting None, All, and Any predicate features.

# Neo4J Cypher code
match p=(a:Begin)-[:HOP*1..]->(z:Finish)
the place none(node IN nodes(p) the place node.class="D")
return p

Question ID 2 makes use of the scale back() perform to calculate complete distance throughout relationships. This question is supported however wants minor modification as detailed within the Neptune documentation on rewriting the Cypher scale back() perform in openCypher.

# Neo4J Instance
match p=(a:airport {code: 'ANC'})-[r:route*1..3]->(z:airport {code: 'AUS'})
return p, scale back(totalDist=0, r in relationships(p) | totalDist + r.dist) AS totalDist
ORDER BY totalDist LIMIT 5

Question IDs 3 and 4 use the FOREACH clause to replace node properties alongside a path. These queries aren’t supported and require an entire rewrite utilizing the UNWIND clause mixed with acceptable sample matching, as defined within the Neptune documentation on rewriting the Cypher FOREACH clause.

# Neo4J Instance
MATCH p=(:airport {code: 'ANC'})-[*1..2]->({code: 'AUS'})
FOREACH (n IN nodes(p) | SET n.visited = true)
MATCH p=(begin)-[*]->(end) WHERE begin.identify="A" AND end.identify="D" FOREACH (n IN nodes(p) | SET n.marked = true)"

Question ID 5 makes use of the Neo4j APOC process apoc.do.when() for conditional logic. This question isn’t supported as a result of APOC procedures are Neo4j-specific. It requires a rewrite utilizing the alternate options constructed into Neptune, resembling checklist comprehension capabilities with the UNWIND clause, as defined within the Neptune documentation on rewriting Neo4j APOC procedures.

# Neo4J Instance
MATCH (n:airport {area: '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 worth
WITH gather(worth.n) as airports
RETURN measurement([a in airports where a.is_large_airport]) as large_airport_count,
measurement([a in airports where NOT a.is_large_airport]) as small_airport_count

Question ID 6 makes use of the APOC process apoc.case() for case-based logic. This question isn’t supported within the Neptune openCypher implementation and requires rewriting utilizing the native capabilities Neptune. Whereas the instrument identifies this incompatibility, it doesn’t present a particular alternative suggestion for this APOC perform. See the Neptune compatibility documentation with Neo4j to search out steerage on changing unsupported APOC features into Neptune-supported openCypher queries or equal Neptune features.

Executing the compatibility examine and deciphering outcomes

This part demonstrates the right way to use the openCypher Compatibility Checker to research the enter file. The instrument accepts two parameters: --input to specify the supply file containing queries to course of (for instance, --input queries.json), and --output to outline the place the migration outcomes ought to be saved (for instance, --output outcomes.json). When executed, the appliance reads queries from the enter file, applies compatibility evaluation and transformation logic, and writes the outcomes to the output file. This migration helper streamlines the method of changing queries from Neo4j’s Cypher dialect to openCypher-compliant syntax suitable with Neptune.

java -jar NeptuneNeo4jMigrationHelper-1.0.jar --input queries.json --output outcomes.json

After operating the previous command, the compatibility instrument evaluation outcomes are written to the outcomes.jsonfile. You may view the output by opening this file in any textual content editor or JSON viewer. The outcomes file accommodates a structured JSON response with a outcomes array, the place every aspect corresponds to one among your enter queries, matched by its distinctive id. For every question, the output signifies whether or not it’s supported (true or false) and offers an errorDefinitions array that particulars any compatibility points discovered. When a question is unsupported, the error definitions embrace the precise place of the problematic syntax, the identify of the unsupported characteristic, a possible alternative suggestion (if accessible), and a description explaining why the characteristic isn’t supported and the way you would possibly deal with it. This structured format simplifies figuring out which queries want modification and understanding precisely what adjustments are required for Neptune compatibility. The next JSON reveals the outcomes.json file:

{
  "outcomes" : [ {
    "id" : 1,
    "supported" : true,
    "errorDefinitions" : [ ]
  }, {
    "id" : 2,
    "supported" : true,
    "errorDefinitions" : [ ]
  }, {
    "id" : 3,
    "supported" : false,
    "errorDefinitions" : [ {
      "position" : "line 1, column 59 (offset: 58)",
      "name" : "FOREACH",
      "replacement" : "",
      "description" : "FOREACH is not supported in this release"
    } ]
  }, {
    "id" : 4,
    "supported" : false,
    "errorDefinitions" : [ {
      "position" : "line 1, column 76 (offset: 75)",
      "name" : "FOREACH",
      "replacement" : "",
      "description" : "FOREACH is not supported in this release"
    } ]
  }, {
    "id" : 5,
    "supported" : false,
    "errorDefinitions" : [ {
      "position" : "line 1, column 37 (offset: 36)",
      "name" : "CALL",
      "replacement" : "",
      "description" : "CALL clause inputs of type GreaterThanOrEqual(Property(Variable(n),PropertyKeyName(runways,None)),SignedDecimalIntegerLiteral(3))"
    }, {
      "position" : "line 1, column 37 (offset: 36)",
      "name" : "apoc.do",
      "replacement" : "List Comprehension capabilities with the UNWIND clause",
      "description" : "apoc.do is not supported in this release but try replacing with List Comprehension capabilities with the UNWIND clause"
    } ]
  }, {
    "id" : 6,
    "supported" : false,
    "errorDefinitions" : [ {
      "position" : "line 1, column 37 (offset: 36)",
      "name" : "apoc.case",
      "replacement" : "",
      "description" : "apoc.case is not supported in this release"
    } ]
  } ]
}

The instrument generates an in depth report displaying:

  • Whether or not every question is supported
  • The place of unsupported components within the cypher question
  • Names of unsupported features and clauses
  • Steered replacements (if accessible)
  • Detailed error descriptions

Widespread migration situations

This information outlines key variations and technical issues for a profitable migration.

Predicate features

  • NONE(): Could be applied utilizing checklist comprehension
  • ALL(): Could be rewritten utilizing checklist comprehension
  • ANY(): Achievable by checklist comprehension patterns

Aggregation and processing

  • scale back(): Could be applied utilizing a mix of:
    • Record comprehension
    • UNWIND clause
    • Applicable aggregation features

Management circulate modifications

  • FOREACH clause:
    • Substitute with UNWIND operations
    • Mix with acceptable sample matching
    • Use a number of MATCH or CREATE statements as wanted

Process variations

  • Neo4j APOC procedures:
    • Use the built-in Neptune alternate options the place accessible
    • Implement customized options for unsupported functionalities
    • Use the built-in graph operations accessible in Neptune

For extra data, see Rewriting Cypher queries to run in openCypher on Neptune.

Conclusion

The openCypher Compatibility Checker streamlines Neo4j to Neptune migrations by figuring out compatibility points early and offering clear steerage on essential adjustments. Whereas the instrument automates incompatibility detection, it’s best to fastidiously consider every case and completely take a look at rewritten queries to confirm that they keep the supposed performance in a Neptune openCypher implementation.


In regards to the authors

Justin John

Justin John

Justin is a Database Specialist Options Architect with AWS. Previous to AWS, Justin labored for big enterprises in know-how, financials, airways, and vitality verticals, serving to them with database and resolution architectures. In his spare time, you’ll discover him exploring the nice open air by mountain climbing and touring to new locations.

autDave Bechberger

Dave Bechberger

Dave is a Sr. Graph Architect with the Amazon Neptune crew. He used his years of expertise working with prospects to construct graph database-backed purposes as inspiration to co-author Graph Databases in Motion by Manning.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles