Neo4j backend

drm.neo4j_graph exposes the persistent backend that stores graphs in Neo4j. It supports the same core concepts as the in-memory backend while adding database connectivity, foreign-key checks, and graph persistence.

Neo4jGraph — Full Neo4j driver integration layer for the DRM graph model.

Provides graph operations (insert, update, delete nodes and relations) with FK validation, cascade delete, and WeakNode parent propagation.

class drm.neo4j_graph.Neo4jGraph(url, user, password, database=None)[source]

Bases: object

Neo4j-backed graph store for the DRM document representation model.

This class wraps the Neo4j Python driver and provides high-level operations for managing graph nodes and relations with foreign key validation, cascade delete strategies (CASCADE, RESTRICT, SET NULL), and WeakNode parent-child propagation.

Example

>>> graph = Neo4jGraph(
...     url="bolt://localhost:7687",
...     user="neo4j",
...     password="secret",
...     database="mydb",
... )
>>> doc = Node(pk={"doc": "DOC-001"}, main_label="Document")
>>> graph.insertNode(doc, replace=True)
>>> graph.close()
Parameters:
  • url (str) – Neo4j connection URL (e.g. bolt://localhost:7687).

  • user (str) – Authentication username.

  • password (str) – Authentication password.

  • database (str | None) – Target database name. Defaults to the Neo4j default.

__init__(url, user, password, database=None)[source]
Parameters:
Return type:

None

insertNode(node, insert_parent=True, update=False, replace=False, **kwargs)[source]

Insert a node into the Neo4j database.

For WeakNode instances, the parent node is inserted first if insert_parent=True. String dependencies (dependencies attribute) are automatically materialised as Valor nodes connected by typed edges.

Parameters:
  • node (Node) – The node to insert.

  • insert_parent (bool) – If the node is a WeakNode, insert its parent first. Defaults to True.

  • update (bool) – If True, MERGE the node and update attributes without deleting it. Use when adding new attributes to an existing node. Defaults to False.

  • replace (bool) – If True and the node already exists, delete it (with detach) and create a fresh one. The caller must recreate relations. Defaults to False.

  • kwargs (Any)

Returns:

The Neo4j internal node id of the inserted node.

Return type:

int

deleteNode(node, propagation=False, detach=False, on_delete='cascade')[source]

Delete a node and optionally its connected subgraph.

Handles ON DELETE strategies, WeakNode cascade propagation, and FK index cleanup.

Parameters:
  • node (Node) – The node to delete.

  • propagation (bool) – If True, recursively delete child nodes linked via edges with _propagate=TRUE (used by WeakNode).

  • detach (bool) – If True, use Neo4j DETACH DELETE to remove the node and all connected edges.

  • on_delete (str) – Deletion strategy — "cascade" (default), "restrict", or "set_null".

Returns:

True if the node was deleted, False if deletion was refused (e.g. RESTRICT with existing edges) or the node was not found.

Return type:

bool

checkNode(node, **kwargs)[source]

Check if a node exists in the database.

Looks up the node by its neo4j_id if set, otherwise searches by main_label and primary key.

Parameters:
  • node (Node) – The node to look up.

  • kwargs (Any)

Returns:

The Neo4j internal node id if found, None otherwise.

Return type:

int | None

insertRelation(rel, update=False, replace=False, **kwargs)[source]

Insert a directed relation (edge) between two nodes.

Validates that both source and destination nodes exist before creating the edge (FK constraint).

Parameters:
  • rel (Relation) – The relation to insert, containing source node, destination node, and relation type.

  • update (bool) – If True, MERGE the relation and update attributes without deleting it. Defaults to False.

  • replace (bool) – If True and the relation already exists, delete it and create a fresh one. Defaults to False.

  • kwargs (Any)

Returns:

The Neo4j internal relation id of the inserted relation.

Raises:

RuntimeError – If the source or destination node does not exist in the database (FK violation).

Return type:

int

create(migration, update=False, replace=False)[source]

Bulk import nodes and relations from a migration plan.

Iterates over the node and relation lists, inserting each with a progress bar. Uses insertNode and insertRelation internally.

Parameters:
  • migration (Tuple[List[Node], List[Relation]]) – A tuple (node_list, relation_list) where each list contains Node or Relation instances.

  • update (bool) – Passed to insertNode / insertRelation.

  • replace (bool) – Passed to insertNode / insertRelation.

Return type:

None

get_node_ids()[source]

Return all internal node ids in the graph.

Return type:

List[int]

get_nodes()[source]

Alias for get_node_ids() for backward compatibility.

Return type:

List[int]

get_node_pks()[source]

Return all primary keys of nodes in the graph.

Return type:

List[Dict[str, Any]]

get_edges()[source]

Return all edges as (src_id, dst_id, rel_type) tuples.

Return type:

List[Tuple[int, int, str]]

get_edge_attrs(u, v, key)[source]

Return attributes stored for an edge.

Parameters:
Return type:

Dict[str, Any] | None

query(filter_dict=None, projection=None, sort=None, limit_val=None, params=None)[source]

Execute a raw Cypher query and return results as a list of dicts.

Hybrid API — the first argument accepts either:

  • str — a Cypher query string (MATCH, CREATE, DELETE, SET, RETURN, ORDER BY, LIMIT, aggregations, parameter substitution via $name).

  • dict — not supported by Neo4jGraph (raises ValueError); use a Cypher string instead.

Each record is a dict mapping return aliases to values. Node values are dicts with labels and properties keys. Relation values are dicts with type, start_node, end_node, and properties keys. Primitive values are returned as-is.

Parameters:
  • filter_dict (Dict[str, Any] | str | None) – Cypher query string for Neo4jGraph. MongoDB-style dicts are not supported — use Cypher instead.

  • projection (Dict[str, int] | None) – Ignored for Cypher queries (use RETURN aliases).

  • sort (Tuple[str, int] | None) – Ignored for Cypher queries (use ORDER BY).

  • limit_val (int | None) – Ignored for Cypher queries (use LIMIT).

  • params (Dict[str, Any] | None) – Optional parameter dict for $name substitution.

Returns:

A list of dicts, one per result record.

Return type:

List[Dict[str, Any]]

Example

>>> graph.query("MATCH (n) RETURN n LIMIT 5")
>>> graph.query(
...     "MATCH (n:Person {name: $name}) RETURN n",
...     params={"name": "Alice"},
... )
create_group(strong_node, weak_nodes=None, weak_relations=None, **kwargs)[source]

Create a strong node together with its WeakNodes and WeakRelations atomically using a Neo4j transaction.

All operations run inside a single begin_transaction. If any step fails the transaction is rolled back.

Parameters:
  • strong_node (Node) – The root (non-weak) node of the group.

  • weak_nodes (List[Node] | None) – Optional list of WeakNode instances.

  • weak_relations (List[Relation] | None) – Optional list of WeakRelation instances.

  • kwargs (Any)

Returns:

The Neo4j internal id of the strong_node.

Raises:

RuntimeError – If any part of the group creation fails.

Return type:

int

init_propagation(background=False, progress_callback=None)[source]

Scan the backend graph and initialize propagation properties.

See GraphStore.init_propagation for details.

Parameters:
Return type:

bool

close()[source]
Return type:

None

enable_vector_index(name, dimensions, space='cosine', **kwargs)[source]

Neo4j backend does not support vector indexes.

Parameters:
Return type:

None

query_vector_index(name, vector, top_k=5)[source]

Neo4j backend does not support vector queries.

Parameters:
Return type:

List[int]

get_subdocuments(strong_node)[source]

Return all subdocuments (WeakNodes) reachable from strong_node through _propagate edges.

Follows edges in their declared direction (parent → child) and returns every descendant WeakNode as a dict with label, pk, and properties keys.

Parameters:

strong_node (Node) – The root (non-weak) node.

Returns:

A list of dicts, one per subdocument.

Return type:

List[Dict[str, Any]]

schema_yaml(db_name)[source]

Introspect the Neo4j database and return a YAML schema description.

Queries db.labels() and db.relationshipTypes() to collect all labels, properties, relationship types, and counts.

Parameters:

db_name (str) – Human-readable database name (e.g. "got").

Returns:

A YAML string suitable for code generation.

Return type:

str