An object mapper for the neo4j graph database.
npx @tessl/cli install tessl/pypi-neomodel@5.5.0An Object Graph Mapper (OGM) for the Neo4j graph database, built on the neo4j-python-driver. Neomodel provides familiar class-based model definitions with proper inheritance, a powerful query API, schema enforcement through cardinality restrictions, full transaction support, and both synchronous and asynchronous programming patterns.
pip install neomodelimport neomodelCommon patterns for working with neomodel:
from neomodel import (
StructuredNode, StringProperty, IntegerProperty,
RelationshipTo, config
)For async operations:
from neomodel import (
AsyncStructuredNode, AsyncRelationshipTo, adb
)from neomodel import (
StructuredNode, StringProperty, IntegerProperty,
RelationshipTo, config
)
# Configure database connection
config.DATABASE_URL = 'bolt://neo4j:password@localhost:7687'
# Define node models
class Person(StructuredNode):
name = StringProperty(unique_index=True, required=True)
age = IntegerProperty()
# Define relationships
friends = RelationshipTo('Person', 'FRIENDS_WITH')
class Movie(StructuredNode):
title = StringProperty(required=True)
year = IntegerProperty()
# Create and connect nodes
person = Person(name="Alice", age=30).save()
movie = Movie(title="The Matrix", year=1999).save()
# Query nodes
alice = Person.nodes.get(name="Alice")
matrix_movies = Movie.nodes.filter(title__contains="Matrix")
# Traverse relationships
alice_friends = alice.friends.all()Neomodel uses a dual-architecture approach:
StructuredNode, db, and sync-specific classesAsyncStructuredNode, adb, and async-specific classesKey components:
Core functionality for defining and working with graph nodes, including model definitions, CRUD operations, and property management for both synchronous and asynchronous contexts.
class StructuredNode:
def save(self): ...
def delete(self): ...
def refresh(self): ...
@classmethod
def create(cls, **kwargs): ...
@classmethod
def get_or_create(cls, **kwargs): ...
class AsyncStructuredNode:
async def save(self): ...
async def delete(self): ...
async def refresh(self): ...
@classmethod
async def create(cls, **kwargs): ...
@classmethod
async def get_or_create(cls, **kwargs): ...Comprehensive set of typed properties for node and relationship attributes, including basic types, specialized validation, date/time handling, and indexing support.
class StringProperty:
def __init__(self, max_length=None, choices=None, **kwargs): ...
class IntegerProperty:
def __init__(self, **kwargs): ...
class DateTimeProperty:
def __init__(self, default_now=False, **kwargs): ...
class JSONProperty:
def __init__(self, **kwargs): ...
class UniqueIdProperty:
def __init__(self, **kwargs): ...Powerful relationship definition and traversal system with cardinality constraints, supporting both simple connections and complex relationship models with properties.
class RelationshipTo:
def __init__(self, cls_name, relation_type, **kwargs): ...
class RelationshipFrom:
def __init__(self, cls_name, relation_type, **kwargs): ...
class StructuredRel:
def save(self): ...
def delete(self): ...
# Cardinality classes
class One: ...
class ZeroOrOne: ...
class OneOrMore: ...
class ZeroOrMore: ...Advanced querying capabilities including filtering, ordering, aggregation, and graph traversal operations with support for complex WHERE clauses and relationship navigation.
class NodeSet:
def filter(self, **kwargs): ...
def get(self, **kwargs): ...
def all(self): ...
def order_by(self, *props): ...
def limit(self, count): ...
class Q:
def __init__(self, **kwargs): ...
def __and__(self, other): ...
def __or__(self, other): ...
class Traversal:
def traverse(self, *relationships): ...Database connection management, schema operations, transaction support, and administrative functions for maintaining Neo4j database state.
# Database instances
db: Database # Sync database interface
adb: AsyncDatabase # Async database interface
# Utility functions
def clear_neo4j_database(): ...
def install_all_labels(): ...
def change_neo4j_password(new_password): ...
def drop_constraints(): ...
def drop_indexes(): ...Comprehensive exception classes for error handling in neomodel operations, providing detailed information about various error conditions during database operations, model definitions, and data validation.
# Base exceptions
class NeomodelException(Exception): ...
class DoesNotExist(NeomodelException): ...
class MultipleNodesReturned(ValueError, NeomodelException): ...
# Property exceptions
class RequiredProperty(NeomodelException): ...
class UniqueProperty(ConstraintValidationFailed): ...
class InflateError(ValueError, NeomodelException): ...
class DeflateError(ValueError, NeomodelException): ...
# Cardinality exceptions
class CardinalityViolation(NeomodelException): ...
class AttemptedCardinalityViolation(NeomodelException): ...
# Model definition exceptions
class NodeClassNotDefined(ModelDefinitionException): ...
class RelationshipClassNotDefined(ModelDefinitionException): ...# Core configuration variables
DATABASE_URL: str # Neo4j connection URL (default: "bolt://neo4j:foobarbaz@localhost:7687")
DATABASE_NAME: str # Specific database name for multi-database instances
DRIVER: object # Custom Neo4j driver instance
FORCE_TIMEZONE: bool # Force timezone handling (default: False)
# Connection configuration options
CONNECTION_ACQUISITION_TIMEOUT: float # Timeout for acquiring connections (default: 60.0)
CONNECTION_TIMEOUT: float # Connection timeout in seconds (default: 30.0)
ENCRYPTED: bool # Enable encrypted connection (default: False)
KEEP_ALIVE: bool # Enable connection keep-alive (default: True)
MAX_CONNECTION_LIFETIME: int # Maximum connection lifetime in seconds (default: 3600)
MAX_CONNECTION_POOL_SIZE: int # Maximum connection pool size (default: 100)
MAX_TRANSACTION_RETRY_TIME: float # Maximum transaction retry time (default: 30.0)
RESOLVER: object # Custom address resolver (default: None)
TRUSTED_CERTIFICATES: object # Certificate trust configuration
USER_AGENT: str # User agent string for driver connectionsConfiguration is handled through the neomodel.config module, allowing connection URL specification, custom driver instances, and comprehensive connection tuning options. All connection parameters correspond to Neo4j Python driver configuration options.
Neomodel provides several CLI scripts for database management, schema operations, and development utilities.
# Install database indexes and constraints for model schemas
neomodel_install_labels someapp.models
# Remove all indexes and constraints from database
neomodel_remove_labels
# Inspect existing database and generate Python model definitions
neomodel_inspect_database --write-to models.py
# Generate database diagram in PlantUML or Arrows.app format
neomodel_generate_diagram --file-type puml --write-to-dir diagrams/Available Scripts:
neomodel_install_labels - Setup indexes and constraints for neomodel schemasneomodel_remove_labels - Drop all indexes and constraints from databaseneomodel_inspect_database - Inspect database schema and generate model definitionsneomodel_generate_diagram - Generate database visualization diagramsAll scripts support --db parameter for custom Neo4j connection URLs and will use NEO4J_BOLT_URL environment variable as fallback.
Neomodel provides integration utilities for converting query results to popular data science libraries.
# NumPy integration (requires numpy package)
from neomodel.integration.numpy import to_ndarray
def to_ndarray(query_results: tuple, dtype=None, order="K"):
"""
Convert cypher query results to numpy ndarray.
Args:
query_results (tuple): Results from db.cypher_query()
dtype: Optional numpy data type
order (str): Array ordering ('K', 'C', 'F', 'A')
Returns:
numpy.ndarray: Query results as numpy array
"""
# Pandas integration (requires pandas package)
from neomodel.integration.pandas import to_dataframe, to_series
def to_dataframe(query_results: tuple, index=None, dtype=None):
"""
Convert cypher query results to pandas DataFrame.
Args:
query_results (tuple): Results from db.cypher_query()
index: Optional row index for DataFrame
dtype: Optional pandas data type
Returns:
pandas.DataFrame: Query results as DataFrame
"""
def to_series(query_results: tuple, field=0, index=None, dtype=None):
"""
Convert cypher query results to pandas Series.
Args:
query_results (tuple): Results from db.cypher_query()
field (int): Column index to extract (default: 0)
index: Optional row index for Series
dtype: Optional pandas data type
Returns:
pandas.Series: Single column as Series
"""from neomodel import db
from neomodel.integration.pandas import to_dataframe
from neomodel.integration.numpy import to_ndarray
# Execute cypher query
results = db.cypher_query("MATCH (u:User) RETURN u.name AS name, u.age AS age")
# Convert to pandas DataFrame
df = to_dataframe(results)
print(df)
# name age
# 0 Alice 30
# 1 Bob 25
# Convert to numpy array
arr = to_ndarray(results)
print(arr)
# [['Alice' 30]
# ['Bob' 25]]# Direction constants
OUTGOING: int # Value: 1
INCOMING: int # Value: -1
EITHER: int # Value: 0
# Base classes
class NeomodelException(Exception): ...
class DoesNotExist(NeomodelException): ...
class RequiredProperty(ValueError): ...
class UniqueProperty(ValueError): ...