Skip to main content

cypher-graphdb

One Python API for Cypher graph databases — Apache AGE (a PostgreSQL extension) and Memgraph (Bolt) today, others behind the same seam. Plus optional Pydantic typing and an interactive CLI over the same surface.

Cypher is close to a standard; the databases that speak it are not. AGE keeps properties in a single agtype column and cannot bind parameters inside UNWIND; Memgraph is a native graph store with per-property indexes and real streaming. cypher-graphdb absorbs those differences without pretending they do not exist.

Why cypher-graphdb

  1. Portable, honestly. One API across backends, with the differences declared rather than discovered. Anything a backend may not support sits behind has_capability(...), so you branch on a fact instead of catching a failure mid-load.

  2. Never in your way. Every layer above raw Cypher is optional and the database stays reachable — down to execute_sql() against PostgreSQL/AGE directly. Dropping a level for one awkward query is a supported move.

  3. Typing you opt into. Register Pydantic models on a ModelProvider you construct and results hydrate into your own classes. No global registry, so importing a module has no process-wide effect and two graphs can use the same label for different things.

  4. Built for bulk. bulk_create_nodes / bulk_create_edges batch through UNWIND (or a direct SQL path), and property indexing is first-class — because a graph load that ignores indexes is a graph load that never finishes.

  5. Safe by construction. Query building returns (query, params); read-only mode rejects writing clauses in the parser before they reach the backend; results and their statistics come back as one immutable value, which is what makes pooling and concurrency safe.

Feature shortlist

  • Backends — age (Apache AGE on PostgreSQL) and memgraph (Bolt). Both drivers ship as regular dependencies; there is no per-backend extra. Add another by implementing the CypherBackend ABC.
  • Capability model — BackendCapability covers property indexes, unique constraints, full-text and vector indexes, streaming, pagination, multiple labels and more. Optional methods raise NotImplementedError; the check is how you avoid that.
  • Typed models — mp.node() / mp.edge() / mp.relation() on an explicit ModelProvider, with Cardinality on declared relationships and JSON-schema generation from the models.
  • Queries — parameterized execute(cypher, params=…), optional result unnesting, QueryResult with execution statistics, chunked streaming, and pagination via Page.
  • Graph objects — GraphNode, GraphEdge, GraphPath, Graph, with match criteria (MatchNodeCriteria, MatchEdgeCriteria, MatchNodeById, …) that build parameterized Cypher rather than concatenated strings.
  • Bulk + indexes — batched node/edge creation, create_property_index, drop_index, list_indexes returning normalized IndexInfo.
  • Client-side analysis — graphops over a materialized Graph: root_nodes, incoming_nodes / outgoing_nodes, build_tree, has_cycles, density.
  • Import / export — a format registry: CSV, JSON and YAML built in, Excel via [excel], and your own formats registrable with @data_format. Includes a hierarchical round-trip format with gid_ deduplication.
  • Safety — read-only mode, connection guards, credential-redacting settings.
  • Pooling — CypherGraphDBPool with a size bound and idle TTL.
  • CLI — cypher-graphdb, interactive or scripted, over every backend.

Levels of abstraction

Four layers, each usable on its own, all on the same connection and transaction.

TYPED OBJECTS     your Pydantic classes, registered on a ModelProvider
GRAPH OBJECTS     GraphNode / GraphEdge / GraphPath / Graph + match criteria
CYPHER            execute(cypher, params=…) → QueryResult
BACKEND SQL       execute_sql() — straight to PostgreSQL/AGE

CypherGraphDB is a facade composed of mixins — connection, batch, indexing, schema, search, SQL, streaming, pagination — so every layer is reachable from one object. Details in docs/usage/index.md.

Example

from cypher_graphdb import CypherGraphDB, GraphNode, GraphEdge

with CypherGraphDB(backend="memgraph", connect_url="bolt://localhost:7687") as db:
    alice = db.create_or_merge(GraphNode(label_="Person",
                                         properties_={"name": "Alice", "age": 30}))
    acme  = db.create_or_merge(GraphNode(label_="Company",
                                         properties_={"name": "TechCorp"}))
    db.create_or_merge(
        GraphEdge.build(alice, acme, label_="WORKS_FOR", properties_={"since": 2020})
    )
    db.commit()

    for name, company in db.execute(
        "MATCH (p:Person)-[:WORKS_FOR]->(c:Company) RETURN p.name, c.name"
    ):
        print(f"{name} works for {company}")

Swap backend="age" and a postgresql:// URL and the rest is unchanged. Note that nothing commits implicitly — not create_or_merge, not leaving the with block.

With typed models

Models register on a provider you construct, and the provider is wired to the connection:

from cypher_graphdb import CypherGraphDB, GraphNode, GraphEdge, ModelProvider

mp = ModelProvider()

@mp.node(label="Product")
@mp.relation(rel_type="USES_TECHNOLOGY", to_type="Technology")
class Product(GraphNode):
    name: str
    multi_tenancy: bool | None = None

@mp.edge(label="USES_TECHNOLOGY")
class UsesTechnology(GraphEdge):
    version: str | None = None

db = CypherGraphDB(backend="age", model_provider=mp)

There is no global registry — importing this module has no process-wide effect, so two graphs may define the same label without colliding. See docs/adr/0001-explicit-model-providers.md.

Loading data in bulk

db.bulk_create_nodes(rows, label="Component", batch_size=200)
db.create_property_index("Component", "symbol", "name")   # before the edges
db.bulk_create_edges(edges, src_refs=…, dst_refs=…,
                     src_label="Component", dst_label="Component",
                     src_ref_prop="symbol", dst_ref_prop="symbol")

Order matters: nodes, then the indexes the edge load matches on, then edges. docs/usage/bulk-and-indexes.md explains why, and what each backend actually does with an index.

Install

Requires Python 3.14+.

Lean core, optional CLI. The default install carries only what the library needs — both backend drivers included, so there is no per-backend extra. The interactive CLI's dependencies (typer, rich, prompt_toolkit, art, lark) and Excel support (openpyxl) are opt-in. The core has no numpy and no terminal-UI stack.

Install Adds Use when
cypher-graphdb core library, both backends embedding the library in your own program
cypher-graphdb[excel] openpyxl you need Excel import/export
cypher-graphdb[cli] typer, rich, prompt_toolkit, art, lark (+ [excel]) you want the cypher-graphdb command
cypher-graphdb[dev] cli + toolchain development (implies [cli])
pip install cypher-graphdb          # library only
pip install 'cypher-graphdb[cli]'   # + the cypher-graphdb command
# or
uv add 'cypher-graphdb[cli]'

The distribution is cypher-graphdb; the import name is cypher_graphdb. cypher-graphdb appears on your PATH with the [cli] extra; invoking it without that extra reports which install you need rather than a bare import error.

Connection details come from arguments, the environment, or a .env file:

export CGDB_BACKEND=age
export CGDB_CINFO=postgresql://postgres:postgres@localhost:5432/graphdb
export CGDB_GRAPH=my_graph

Then start with docs/usage/getting-started.md.

The CLI

cypher-graphdb --graph my_graph                    # interactive REPL
cypher-graphdb --graph my_graph -e "labels"        # execute and exit
cypher-graphdb --graph my_graph --json -e "indexes"
cypher-graphdb schema generate -m ./graph_models/ -o ./schemas/   # no database needed

Anything that is not a recognised command runs as Cypher. Output is a table interactively and JSON when scripted. Full command set in docs/usage/cli.md.

Develop

Requires uv and task; integration tests need Docker.

task install           # venv + editable install
task fct               # format + check + typecheck + unit tests — the local loop
task test:all          # unit + integration
task run:cli           # run cypher-graphdb from the venv

Conventions and the release flow are in CONTRIBUTING.md.

Layout

src/cypher_graphdb/
  backend.py            the CypherBackend ABC + BackendCapability
  cyphergraphdb/        the facade and its mixins (connection, batch, indexing,
                        schema, search, sql, streaming, pagination, criteria)
  backends/             age/ and memgraph/ implementations
  cypherquery/          the opt-in fluent query builder
  cypherbuilder.py      parameterized Cypher construction
  cypherparser.py       query parsing (drives read-only mode)
  modelprovider.py      explicit model registries
  models.py             GraphNode / GraphEdge / GraphPath / Graph
  graphops.py           client-side analysis over a materialized Graph
  tools/                import / export (CSV, Excel, JSON, YAML) -- needs [cli]
  cli/                  cypher-graphdb — REPL, commands, rendering
docs/                   usage/, design/, adr/

Documentation

Plain markdown with OKF frontmatter; there is no doc build and no generated API reference. Docstrings in the code are the API reference.

Contributing & License

Contributions welcome — see CONTRIBUTING.md (and AGENTS.md if you use an AI coding assistant). Licensed under the Apache License 2.0 — see LICENSE.md.

Metadata

Release files for cypher-graphdb 0.7.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cypher-graphdb 0.7.2
File Size Uploaded
cypher_graphdb-0.7.2.tar.gz 699.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cypher-graphdb 0.7.2
File Interpreter ABI Platform
cypher_graphdb-0.7.2-py3-none-any.whl Python 3 none any Details

Total release size: 1.2 MB

Release files / cypher_graphdb-0.7.2.tar.gz

Download URL cypher_graphdb-0.7.2.tar.gz
Size 699.8 kB
Tags Source
SHA-256 checksum
How to use checksums
ce1af98bedb59c6cea62b4ee652c638168b1a9d6461f0ba9cf3ca87c7bac3d86
BLAKE2b-256 checksum
How to use checksums
7b47e4c865ed259a0da7db1a70995ad403462b1ad4a189fbba375d449f7de2a6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release files / cypher_graphdb-0.7.2-py3-none-any.whl

Download URL cypher_graphdb-0.7.2-py3-none-any.whl
Size 538.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1aaa12bf1997fb1ae2b3a906253bb49dd44d5a25b3dd42a0ba76ba38f032760a
BLAKE2b-256 checksum
How to use checksums
c283d44f4d9fc9f635bbc6c330987e259d251b6797dba5097db6a4a89ff1cb99
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release history Release notifications | RSS feed

0.7.3

2 release files

This release

0.7.2 This release

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.9

2 release files

0.2.8

2 release files

0.2.7

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.2

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page