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:
objectNeo4j-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:
- 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 (dependenciesattribute) are automatically materialised asValornodes 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:
- 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 DELETEto 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:
- checkNode(node, **kwargs)[source]
Check if a node exists in the database.
Looks up the node by its
neo4j_idif set, otherwise searches bymain_labeland primary key.
- 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:
- 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
insertNodeandinsertRelationinternally.
- get_nodes()[source]
Alias for
get_node_ids()for backward compatibility.
- 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
labelsandpropertieskeys. Relation values are dicts withtype,start_node,end_node, andpropertieskeys. 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
RETURNaliases).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
$namesubstitution.
- Returns:
A list of dicts, one per result record.
- Return type:
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:
- Returns:
The Neo4j internal id of the
strong_node.- Raises:
RuntimeError – If any part of the group creation fails.
- Return type:
- init_propagation(background=False, progress_callback=None)[source]
Scan the backend graph and initialize propagation properties.
See GraphStore.init_propagation for details.
- enable_vector_index(name, dimensions, space='cosine', **kwargs)[source]
Neo4j backend does not support vector indexes.
- get_subdocuments(strong_node)[source]
Return all subdocuments (WeakNodes) reachable from strong_node through
_propagateedges.Follows edges in their declared direction (parent → child) and returns every descendant WeakNode as a dict with
label,pk, andpropertieskeys.