Show HN: We built a type-safe Python ORM for RedisGraph/FalkorDB
6 コメント
For other coding options, we added spring-data based similar library (Java users):
https://github.com/FalkorDB/spring-data-falkordb
And for Go developers:
https://github.com/FalkorDB/falkordb-go-orm
This looks solid, the type safety and automatic escaping alone would've saved me hours debugging Cypher strings. The batching is smart too. Curious how it handles variable-length paths though, since that's where most ORMs get messy. The AI agent memory use case makes a lot of sense.
Great question — variable-length paths are fully supported in the query builder:
# Friends of friends (1 to 3 hops)
*Variants:* - Unbounded: `FRIEND.variable_length()` → `` - Exact length: `FRIEND.variable_length(2, 2)` → `2` - Min only: `FRIEND.variable_length(1)` → `1..` - Range: `FRIEND.variable_length(1, 3)` → `*1..3`
You can also use the explicit `VariableLength(FRIEND, 1, 3)` constructor if you need to alias the path or reference it later in the query.
The builder handles all edge cases (empty paths, cycles) the same way RedisGraph does — we compile to idiomatic Cypher without abstraction leaks. Raw string patterns still work if you need something exotic.
# Friends of friends (1 to 3 hops)
stmt = select().match(
(User.alias("a"), FRIEND.variable_length(1, 3), User.alias("b"))
).where(
User.alias("a").user_id == 1
).returns(
User.alias("b")
)
Generates: `(a)-[:FRIEND1..3]->(b)`*Variants:* - Unbounded: `FRIEND.variable_length()` → `` - Exact length: `FRIEND.variable_length(2, 2)` → `2` - Min only: `FRIEND.variable_length(1)` → `1..` - Range: `FRIEND.variable_length(1, 3)` → `*1..3`
You can also use the explicit `VariableLength(FRIEND, 1, 3)` constructor if you need to alias the path or reference it later in the query.
The builder handles all edge cases (empty paths, cycles) the same way RedisGraph does — we compile to idiomatic Cypher without abstraction leaks. Raw string patterns still work if you need something exotic.
BTW, in falkordb we also developed an ORM library, also covering RBAC based security features.
https://github.com/FalkorDB/falkordb-py-orm
Thanks for sharing these resources — great to see the FalkorDB ecosystem growing!
We built GraphORM with a focus on type safety + fluent query composition (e.g., indegree()/outdegree() helpers, chainable .match().where().returns()), which we found missing in existing RedisGraph/FalkorDB Python tooling.
Happy to see multiple approaches emerging — diversity helps the ecosystem. We're also planning to expand support beyond RedisGraph/FalkorDB to other Cypher-compatible databases where the query model fits.
Would love to exchange ideas on ORM design patterns if you're open to it.
Sure, BTW as you might be aware, RedisGraph support was discontinued, so FalkorDB is maintained with more features and fully supports all RedisGraph features.
What it does Instead of fragile Cypher:
You write type-safe Python:
Key features: • Type-safe schema with Python type hints • Fluent query builder (select().match().where().returns()) • Automatic batching (flush(batch_size=1000)) • Atomic transactions (with graph.transaction(): ...) • Zero string escaping — O'Connor and "The Builder" just work
Target audience • AI/LLM agent devs: store long-term memory as graphs (User → Message → ToolCall) • Web crawler engineers: insert 10k pages + links in 12 lines vs 80 lines of Cypher • Social network builders: query "friends of friends" with indegree()/outdegree() • Data engineers: track lineage (Dataset → Transform → Output) • Python devs new to graphs: avoid Cypher learning curve
Data insertion: the real game-changer
Raw Cypher nightmare: queries = [ """CREATE (:User {email: "[email protected]", name: "Alice O\\'Connor"})""", """CREATE (:User {email: "[email protected]", name: "Bob \\"The Builder\\""})""" ] for q in queries: graph.query(q) # No transaction safety!
GraphORM bliss: alice = User(email="[email protected]", name="Alice O'Connor") bob = User(email="[email protected]", name='Bob "The Builder"') graph.add_node(alice) graph.add_edge(Follows(alice, bob, since=1704067200)) graph.flush() # One network call, atomic transaction
Try it in 30 seconds pip install graphorm
GitHub: https://github.com/hello-tmst/graphorm
We'd love honest feedback: • Does this solve a real pain point for you? • What's missing for production use? • Any API design suggestions?