Query the database

To run a query on a database, submit a POST request to the following endpoint:

http://<host>:<port>/db/<databaseName>/tx/commit
  • <host> is where the Neo4j instance is located (example localhost, xxx.databases.neo4j.io),

  • <port> is the port on which the Neo4j HTTP server is set to listen on (default 7474),

  • <databaseName> is the database you want to query (example neo4j).

The server wraps the submitted Cypher query in a (implicit) transaction for you. This means that in case any part of the query fails, the database will be reverted back to its status before any part of the query was executed. To control the lifecycle of transactions, see Run transactions.

Each request must include an Authorization header, see Authentication and authorization for more information.

Example request

POST http://localhost:7474/db/neo4j/tx/commit
Accept: application/json;charset=UTF-8
Content-Type: application/json
Authorization: Basic bmVvNGo6dmVyeXNlY3JldA==
{
  "statements": [
    {
      "statement": "MERGE (n:Person {name: $name, age: $age}) RETURN n",
      "parameters": {
        "name": "Alice",
        "age": 42
      }
    }
  ]
}

Example response

200: OK
Content-Type: application/json;charset=utf-8
{
  "results": [ {
    "columns": ["n"],
    "data": [ {
      "row": [ {
        "name": "Alice",
        "age": 42
      } ],
      "meta": [ {
        "id": 36,
        "elementId": "4:0ea4a108-32c5-498c-99e7-95cc67ab5f7d:36",
        "type": "node",
        "deleted": false
      } ]
    } ]
  } ],
  "errors": [],
  "lastBookmarks": [
    "FB:kcwQDqShCDLFSYyZ55XMZ6tffRuQ"
  ]
}

Literal line breaks are not allowed inside Cypher statements submitted through the API (as per JSON specifications). This means that queries should fit on a single line. You can replace line breaks with spaces, as Cypher parses them equivalently.

Query parameters

Do not hardcode or concatenate parameters directly into queries. Instead, always use placeholders and specify the Cypher parameters. This is for:

  1. performance benefits: Neo4j compiles and caches queries, but can only do so if the query structure is unchanged;

  2. security reasons: see protecting against Cypher injection.

Do — Use query parameters
{
  "statements": [
    {
      "statement": "MERGE (n:Person {name: $name, age: $age}) RETURN n",
      "parameters": {
        "name": "Alice",
        "age": 42
      }
    }
  ]
}
Do not — Embed literals in query
{
  "statements": [
    {
      "statement": "MERGE (n:Person {name: 'Alice', age: 42}) RETURN n",
    }
  ]
}

See Cypher Manual → Parameters for more information.

Execute multiple queries

You can send multiple Cypher statements in the same request. The server runs them in sequence, but separate from each other, so a statement cannot reference a variable defined in another statement. The response contains the result of each statement, in order.

Example request

POST http://localhost:7474/db/neo4j/tx/commit
Accept: application/json;charset=UTF-8
Content-Type: application/json
Authorization: Basic bmVvNGo6dmVyeXNlY3JldA==
{
  "statements": [
    { "statement": "RETURN 1" },
    { "statement": "RETURN 2" }
  ]
}

Example response

200: OK
Content-Type: application/json;charset=utf-8
{
  "results": [
    {
      "columns": ["1"],
      "data": [{ "row": [1], "meta": [null] }]
    },
    {
      "columns": ["2"],
      "data": [{ "row": [2], "meta": [null] }]
    }
  ],
  "errors": [],
  "lastBookmarks": [
    "FB:kcwQDqShCDLFSYyZ55XMZ6tffRuQ"
  ]
}

If one of the queries fails, all statements submitted with the request will be rolled back. In the example below, the second statement fails due to a division by 0. The result is that not only no :Number nodes are created (not even the one with val: 1), but no :Person nodes are created either.

Example request

POST http://localhost:7474/db/neo4j/tx/commit
Accept: application/json;charset=UTF-8
Content-Type: application/json
Authorization: Basic bmVvNGo6dmVyeXNlY3JldA==
{
  "statements": [
    {
      "statement": "MERGE (p:Person {name: $name}) RETURN p",
      "parameters": {
        "name": "Bob"
      }
    },
    {
      "statement": "UNWIND [1, 0] AS i MERGE (n:Number {val: 1/i}) RETURN n"
    },
  ]
}

Example response

200: OK
Content-Type: application/json;charset=utf-8
{
  "results": [ {
    "columns": [ "p" ],
    "data": [ {
      "row": [ {
        "name": "Bob"
      } ],
      "meta": [ {
        "id": 8,
        "elementId": "4:0ea4a108-32c5-498c-99e7-95cc67ab5f7d:8",
        "type": "node",
        "deleted": false
      } ]
    ] }
  ] },
  {
    "columns": [ "n" ],
    "data": [ {
      "row": [ {
        "val": 1
      } ],
      "meta": [ {
        "id": 1,
        "elementId": "4:0ea4a108-32c5-498c-99e7-95cc67ab5f7d:1",
        "type": "node",
        "deleted": false
      } ]
    } ]
  } ],
  "errors": [ {
    "code": "Neo.ClientError.Statement.ArithmeticError",
    "message": "/ by zero"
  } ]
}

Queries with CALL {} IN TRANSACTIONS

Take extra care with queries using the Cypher clause CALL {} IN TRANSACTIONS. Because those queries spawn further transactions of their own, there can be unexpected behaviors due to their interaction with the surrounding transaction.

Rollback behaviour

While a failure in any statement will cause all statements in the request to be rolled back, that does not apply to the ones using CALL {} IN TRANSACTIONS. Since the transactions created by that clause get independently committed, the server cannot roll them back in case the other parts fail.

In the example below, even if the second statement fails execution due to the division by zero, the first statement is not reverted. The result is two new :Person nodes.

POST http://localhost:7474/db/neo4j/tx/commit
Accept: application/json;charset=UTF-8
Content-Type: application/json
Authorization: Basic bmVvNGo6dmVyeXNlY3JldA==
{
  "statements": [
    {
      "statement": "UNWIND ['Sofia', 'Greg'] AS name CALL { WITH name CREATE (:Person {name: name}) } IN TRANSACTIONS OF 1 ROWS RETURN name"
    },
    {
      "statement": "UNWIND [1, 0] AS i MERGE (n:Number {val: 1/i}) RETURN n"
    },
  ]
}

Query order

Queries containing CALL {} In TRANSACTIONS must come first in the order of the statements JSON list. Failure to do so will result in an error.

Example request

POST http://localhost:7474/db/neo4j/tx/commit
Accept: application/json;charset=UTF-8
Content-Type: application/json
Authorization: Basic bmVvNGo6dmVyeXNlY3JldA==
{
  "statements": [
    {
      "statement": "MERGE (p:Person {name: $name}) RETURN p.name",
      "parameters": {
        "name": "Bob"
      }
    },
    {
      "statement": "UNWIND [1, 0] AS i CALL { WITH i MERGE (:Number {val: 1/i}) } IN TRANSACTIONS OF 1 ROWS RETURN i"
    },
  ]
}

Example response

200: OK
Content-Type: application/json;charset=utf-8
{
  "results": [ {
    "columns": [ "p.name" ],
    "data": [ {
      "row": [ "Bob" ],
      "meta": [ null ]
    }]
  },
  {
    "columns": [ "i" ],
    "data": []
  } ],
  "errors": [ {
    "code": "Neo.DatabaseError.Statement.ExecutionFailed",
    "message": "Expected transaction state to be empty when calling transactional subquery. (Transactions committed: 0)"
  } ]
}

Server notifications

If the server generates any notifications, they will be returned in the notifications key of the response object (as a list). Notifications include recommendations for performance improvements, warnings about the usage of deprecated features, and other hints about sub-optimal usage of Neo4j.

Example request

POST http://localhost:7474/db/neo4j/tx/commit
Accept: application/json;charset=UTF-8
Content-Type: application/json
Authorization: Basic bmVvNGo6dmVyeXNlY3JldA==
{
  "statements": [
    {
      "statement": "MATCH p=shortestPath((:Person {name: $from})-[*]->(:Person {name: $to})) RETURN p",
      "parameters": {
        "from": "Alice",
        "to": "Bob"
      }
    }
  ]
}

Example response

200: OK
Content-Type: application/json;charset=utf-8
{
  "results": [
    ...
  ],
  "notifications": [
    {
      "code": "Neo.ClientNotification.Statement.UnboundedVariableLengthPattern",
      "severity": "INFORMATION",
      "title": "The provided pattern is unbounded, consider adding an upper limit to the number of node hops.",
      "description": "Using shortest path with an unbounded pattern will likely result in long execution times. It is recommended to use an upper limit to the number of node hops in your pattern.",
      "position": {
        "offset": 21,
        "line": 1,
        "column": 22
      }
    }
  ],
  ...
}

Glossary

Aura

Aura is Neo4j’s fully managed cloud service. It comes with both free and paid plans.

Cypher

Cypher is Neo4j’s graph query language that lets you retrieve data from the database. It is like SQL, but for graphs.

ACID

Atomicity, Consistency, Isolation, Durability (ACID) are properties guaranteeing that database transactions are processed reliably. An ACID-compliant DBMS ensures that the data in the database remains accurate and consistent despite failures.

causal consistency

A database is causally consistent if read and write queries are seen by every member of the cluster in the same order. This is stronger than eventual consistency.

transaction

A transaction is a unit of work that is either committed in its entirety or rolled back on failure. An example is a bank transfer: it involves multiple steps, but they must all succeed or be reverted, to avoid money being subtracted from one account but not added to the other.