Object-Graph Mapping for FalkorDB with Spring Data-inspired patterns
Project description
FalkorDB Python ORM
Object-Graph Mapping for FalkorDB with Spring Data-inspired patterns
FalkorDB Python ORM provides intuitive, annotation-based object-graph mapping for FalkorDB, enabling developers to work with graph databases using familiar ORM patterns inspired by Spring Data.
๐ฏ Project Status
Production Ready! โ The FalkorDB Python ORM is fully implemented, tested, and documented.
๐ Features
Core Capabilities
- ๐ท๏ธ Decorator-based Entity Mapping: Use
@nodeandpropertydecorators for intuitive object-graph mapping - ๐ฆ Repository Pattern: Complete CRUD operations with type-safe
Repository[T] - ๐ ID Management: Auto-generated or manual IDs with
generated_id() - ๐ Type Conversion: Built-in converters for common Python types
- ๐ฏ Multiple Labels: Support for multiple node labels per entity
- ๐จ Type Safety: Full type hints and generic repositories for IDE support
Query Features
- ๐ Derived Query Methods: Auto-generate queries from method names (e.g.,
find_by_name(),count_by_age_greater_than()) - ๐ Comparison Operators: 14+ operators (equals, greater_than, less_than, between, in, etc.)
- ๐ Logical Operators: AND/OR combinations in queries
- ๐ String Operations: CONTAINS, STARTS WITH, ENDS WITH, regex patterns
- ๐ Sorting & Limiting: ORDER BY multiple fields, first/top_N result limiting
- โก Query Caching: Automatic QuerySpec caching for performance
- ๐ Custom Cypher Queries:
@querydecorator with parameter binding - ๐ Aggregation Methods: Built-in
sum(),avg(),min(),max()functions
Relationships
- ๐ Relationship Declaration:
relationship()decorator with full type support - ๐ค Lazy Loading: Relationships loaded on-demand with automatic caching
- โก Eager Loading: Solve N+1 queries with
fetch=['rel1', 'rel2']parameter - ๐ Cascade Operations: Auto-save related entities with
cascade=True - โ๏ธ Bidirectional Relationships: Full support for complex relationship graphs
- ๐ Reverse Relationships:
direction='INCOMING'for inverse traversal - ๐ Circular Reference Handling: Safe handling of circular relationships
Async Support
- โก AsyncRepository: Full async/await support for all CRUD operations
- ๐ Async Relationships: Async lazy loading with
AsyncLazyListandAsyncLazySingle - ๐ Async Derived Queries: Auto-generated async query methods
- ๐ Framework Ready: Perfect for FastAPI, aiohttp, and async Python applications
Production Features
- ๐ Comprehensive Documentation: Complete API reference and migration guides
- ๐ง Enhanced Exceptions: Contextual error messages with structured error information
- ๐ CI/CD Workflows: Automated testing, linting, and publishing
- ๐พ Memory Optimization: Interned strings for repeated values with
@interneddecorator
๐ Future Enhancements (Optional)
- โก Transaction Support: Context managers for transactional operations
- ๐๏ธ Index Management: Decorator-based index and constraint creation
- ๐ฆ Migration System: Schema version management
- ๐ Query Caching: Result caching for performance
๐ Usage
Entity Definition
from falkordb_orm import node, property, relationship, Repository
from typing import Optional, List
@node(labels=["Person", "Individual"])
class Person:
id: Optional[int] = None
name: str = property("full_name") # Maps to 'full_name' in graph
email: str
age: int
friends: List["Person"] = relationship(type="KNOWS", direction="OUTGOING")
company: Optional["Company"] = relationship(type="WORKS_FOR", direction="OUTGOING")
@node("Company")
class Company:
id: Optional[int] = None
name: str
employees: List[Person] = relationship(type="WORKS_FOR", direction="INCOMING")
Repository Usage
from falkordb import FalkorDB
# Connect to FalkorDB
db = FalkorDB(host='localhost', port=6379)
graph = db.select_graph('social')
# Create repository
repo = Repository(graph, Person)
# Create and save
person = Person(name="Alice", email="alice@example.com", age=25)
saved = repo.save(person)
# Derived queries (auto-implemented)
adults = repo.find_by_age_greater_than(18)
alice = repo.find_by_name("Alice")
count = repo.count_by_age(25)
exists = repo.exists_by_email("alice@example.com")
# Eager loading relationships (prevents N+1 queries)
person_with_friends = repo.find_by_id(1, fetch=["friends", "company"])
all_with_friends = repo.find_all(fetch=["friends"]) # Single query!
# Cascade save (auto-saves related entities)
company = Company(name="Acme Corp")
employee = Employee(name="Bob", company=company)
repo.save(employee) # Company automatically saved!
Async Usage (Phase 5)
import asyncio
from falkordb.asyncio import FalkorDB
from falkordb_orm import node, AsyncRepository
from typing import Optional
@node("Person")
class Person:
id: Optional[int] = None
name: str
age: int
async def main():
# Connect to FalkorDB with async client
from redis.asyncio import BlockingConnectionPool
pool = BlockingConnectionPool(max_connections=16, timeout=None, decode_responses=True)
db = FalkorDB(connection_pool=pool)
graph = db.select_graph('social')
# Create async repository
repo = AsyncRepository(graph, Person)
# All operations are async
person = Person(name="Alice", age=25)
saved = await repo.save(person)
# Async derived queries
adults = await repo.find_by_age_greater_than(18)
count = await repo.count()
# Async eager loading
person_with_friends = await repo.find_by_id(1, fetch=["friends"])
print(f"Found {count} people")
asyncio.run(main())
Interned Strings for Memory Optimization (Phase 6)
from falkordb_orm import node, interned
from typing import Optional
@node("User")
class User:
id: Optional[int] = None
name: str
email: str
# Interned properties - deduplicated for memory savings
country: str = interned() # "United States" stored once for all US users
city: str = interned() # "New York" stored once for all NYC users
status: str = interned() # "Active", "Inactive" stored once each
# Memory benefit: Repeated values stored only once!
# Perfect for: countries, cities, status fields, categories, tags
Getting Started
For a complete walkthrough, see QUICKSTART.md.
Custom Queries (Phase 4)
from falkordb_orm import query
class PersonRepository(Repository[Person]):
@query(
"MATCH (p:Person)-[:KNOWS]->(f:Person) WHERE p.name = $name RETURN f",
returns=Person
)
def find_friends(self, name: str) -> List[Person]:
pass
@query(
"MATCH (p:Person) WHERE p.age BETWEEN $min AND $max RETURN p",
returns=Person
)
def find_by_age_range(self, min: int, max: int) -> List[Person]:
pass
๐ Comparison with Current Approach
Before (Raw Cypher)
from falkordb import FalkorDB
db = FalkorDB(host='localhost', port=6379)
g = db.select_graph('social')
# Create manually
g.query('''
CREATE (p:Person {name: $name, email: $email, age: $age})
RETURN p, id(p)
''', {'name': 'Alice', 'email': 'alice@example.com', 'age': 25})
# Query manually
result = g.query('''
MATCH (p:Person) WHERE p.age > $min_age RETURN p
''', {'min_age': 18})
# Manual result processing
for record in result.result_set:
person = record[0]
print(person.properties['name'])
After (ORM - Planned)
from falkordb import FalkorDB
from falkordb_orm import node, Repository
@node("Person")
class Person:
id: Optional[int] = None
name: str
email: str
age: int
db = FalkorDB(host='localhost', port=6379)
graph = db.select_graph('social')
repo = Repository(graph, Person)
# Create with ORM
person = Person(name="Alice", email="alice@example.com", age=25)
saved = repo.save(person)
# Query with derived method
adults = repo.find_by_age_greater_than(18)
# Automatic object mapping
for person in adults:
print(person.name)
๐ Documentation
- Quick Start Guide - Get started in minutes
- Design Document - Comprehensive design and architecture
- API Reference - Complete API documentation
- Decorators -
@node,property(),relationship() - Repository -
RepositoryandAsyncRepository
- Decorators -
- Migration Guide - Migrating from raw FalkorDB client
- Examples - Complete working examples
- Contributing - Contribution guidelines
๐ค Comparison with Spring Data FalkorDB
This project is inspired by Spring Data FalkorDB, bringing similar patterns to Python:
| Feature | Spring Data FalkorDB | falkordb-orm |
|---|---|---|
| Entity Mapping | @Node annotation |
@node decorator |
| Property Mapping | @Property |
property() function |
| Relationships | @Relationship |
relationship() function |
| Repository | FalkorDBRepository<T, ID> |
Repository[T] |
| Query Methods | Method name derivation | Method name derivation |
| Custom Queries | @Query annotation |
@query decorator |
| Transactions | @Transactional |
Session (unit of work) |
| Async Support | โ | โ Planned |
๐ฏ Goals
- Developer Productivity: Reduce boilerplate code and manual Cypher writing
- Type Safety: Leverage Python type hints for better IDE support
- Familiarity: Use patterns developers know from SQLAlchemy, Django ORM, Spring Data
- Performance: Optimize queries, support batching, implement lazy loading
- Flexibility: Support both simple and complex use cases
๐ง Technology Stack
- Python: 3.8+
- FalkorDB Client: falkordb-py
- Type Hints: For IDE support and validation
- Decorators: For entity and query definition
- Generics: For type-safe repositories
๐ฆ Installation
pip install falkordb-orm
Or install from source:
git clone https://github.com/FalkorDB/falkordb-py-orm.git
cd falkordb-py-orm
pip install -e .
๐ก Design Principles
- Convention over Configuration: Sensible defaults with customization options
- Explicit is Better: Clear, readable API over implicit magic
- Performance Matters: Optimize for common use cases
- Pythonic: Follow Python idioms and best practices
- Compatibility: Work seamlessly with existing falkordb-py code
๐ License
MIT License - See LICENSE file for details
๐ Acknowledgments
- Inspired by Spring Data FalkorDB
- Built on top of falkordb-py
- Follows patterns from SQLAlchemy and Django ORM
๐ค Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
๐ฆ Resources
- FalkorDB: falkordb.com
- Discord: FalkorDB Community
- GitHub: FalkorDB Organization
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file falkordb_orm-1.0.1.tar.gz.
File metadata
- Download URL: falkordb_orm-1.0.1.tar.gz
- Upload date:
- Size: 36.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
18c3a1f633fb5eba88da5bff22987104563739a84475714138edba78607a57f3
|
|
| MD5 |
64f7538c4a2f56c3c46add4478811892
|
|
| BLAKE2b-256 |
d6208ebe6f2dd865819947a526f958ad5d42e117f9405150453beb3a548d74f0
|
Provenance
The following attestation bundles were made for falkordb_orm-1.0.1.tar.gz:
Publisher:
publish.yml on FalkorDB/falkordb-py-orm
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
falkordb_orm-1.0.1.tar.gz -
Subject digest:
18c3a1f633fb5eba88da5bff22987104563739a84475714138edba78607a57f3 - Sigstore transparency entry: 731408993
- Sigstore integration time:
-
Permalink:
FalkorDB/falkordb-py-orm@0ed6bd5ec1efd0faa4025d0ca59c4c87d887355c -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/FalkorDB
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0ed6bd5ec1efd0faa4025d0ca59c4c87d887355c -
Trigger Event:
release
-
Statement type:
File details
Details for the file falkordb_orm-1.0.1-py3-none-any.whl.
File metadata
- Download URL: falkordb_orm-1.0.1-py3-none-any.whl
- Upload date:
- Size: 39.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7616869a9b975c85db56655c3e87a468c366994315b501b3a8e252b0cb905c38
|
|
| MD5 |
ccab0c5e865c45c04fc7034f4c46b095
|
|
| BLAKE2b-256 |
fec73e543fd4b2ef2d22ec86943f9c3dd17e2c53852e311d589f5e95e470945a
|
Provenance
The following attestation bundles were made for falkordb_orm-1.0.1-py3-none-any.whl:
Publisher:
publish.yml on FalkorDB/falkordb-py-orm
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
falkordb_orm-1.0.1-py3-none-any.whl -
Subject digest:
7616869a9b975c85db56655c3e87a468c366994315b501b3a8e252b0cb905c38 - Sigstore transparency entry: 731408994
- Sigstore integration time:
-
Permalink:
FalkorDB/falkordb-py-orm@0ed6bd5ec1efd0faa4025d0ca59c4c87d887355c -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/FalkorDB
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0ed6bd5ec1efd0faa4025d0ca59c4c87d887355c -
Trigger Event:
release
-
Statement type: