Parameters and the Python driver

Neo4j · Practical · 14 min

Applications talk to Neo4j through drivers, and using parameters correctly is essential for safety and performance.

Install the official driver with pip install neo4j. Create one driver per application (it manages a connection pool) and close it at shutdown:

driver = GraphDatabase.driver("neo4j://localhost:7687", auth=("neo4j", "secret"))

The neo4j:// scheme enables cluster routing; neo4j+s:// adds TLS (used by Aura). The simplest API is driver.execute_query(query, params..., database_="neo4j"), which runs a query in a retried transaction and returns records, summary, keys. Each Record behaves like a dict and a tuple.

Always use parameters: write $name in Cypher and pass values separately. This prevents Cypher injection, handles quoting and types, and lets Neo4j cache the query plan; string-built queries are re-planned every time. Parameters can be scalars, lists or maps (SET p += $props, UNWIND $rows AS row).

Pass routing_=RoutingControl.READ for read-only queries so a cluster can serve them from secondaries. For multi-statement units of work, use a session with session.execute_write(fn) (managed transactions retried on transient errors), keeping the function free of side effects other than the queries.

Node values come back as neo4j.graph.Node objects with .labels, .element_id and dict-style property access.

Example

from neo4j import GraphDatabase, RoutingControl

URI, AUTH = "neo4j://localhost:7687", ("neo4j", "password")

with GraphDatabase.driver(URI, auth=AUTH) as driver:
    driver.verify_connectivity()
    driver.execute_query(
        "MERGE (p:Person {name: $name}) SET p.born = $born",
        name="Eve", born=1994, database_="neo4j")

    records, summary, keys = driver.execute_query(
        """MATCH (p:Person) WHERE p.born >= $year
           RETURN p.name AS name ORDER BY name""",
        year=1990, database_="neo4j", routing_=RoutingControl.READ)
    print([r["name"] for r in records])          # ['Ann', 'Cy', 'Eve']
    print(summary.result_available_after, "ms")  # e.g. 2 ms

Remember

  • One driver per app; it pools connections
  • execute_query runs a retried transaction and returns records, summary, keys
  • Use $params for values, never string formatting
  • Route reads with RoutingControl.READ

Watch out for

  • Creating a new driver per request, which defeats connection pooling and is slow.

Check yourself

  1. Why pass values as $parameters instead of formatting them into the query string?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: neo4j.com/docs/python-manual/current/