perf(falkordb): push structural Graph queries down to Cypher - #44
Merged
2 commits merged intoJun 29, 2026
Merged
2 commits merged into
2 commits merged into
Conversation
…ling placeholders
…ghborhood in FalkorDBGraphStore
fd5b029
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix #43
depends on #42
Summary
Graphquery methods previously evaluated every filter and traversal in Pythonby scanning the full materialized projection (
all_objects()/all_relations())on each call. For
FalkorDBGraphStorethat means fetching and JSON-decoding everyentity even to answer a narrow query (e.g. "objects of type X" or a 1-hop
neighborhood). This PR lets backends evaluate structural queries close to the data
while keeping query semantics identical across all backends.
What changed
GraphStoreABC —find_objects,find_relations, andneighborhood— with working Python defaults computed overall_objects/all_relations. The base class is the canonical definition oftheir semantics;
InMemoryGraphStoreinherits them unchanged.Graphdelegates to the hooks instead of scanning:Graph.objects(type=...)/query(...)andhas_object_of_type(...)→find_objectsGraph.relations(...)andGraph.get_relations(...)→find_relationsGraph.neighborhood(...)→neighborhoodFalkorDBGraphStoreoverrides the hooks with Cypher so type filters, relationlookups, and neighborhood walks run inside the database (the neighborhood walk uses
a native variable-length path over
AGRelationedges) and return only matchingrows instead of the whole projection.
wherepredicates still run in Python.Graph.objects(where=...)pushes thetype filter down but applies the
whereclause in Python over the returnedsubset, because the structured
datapayload is stored as a JSON string ratherthan as native, indexable properties.
Scope / non-goals
View(frozen snapshot) and whole-graph consumers (diffing, prompt building,pattern matching, the registry, CLI status) legitimately read the full projection
and are intentionally left unchanged.
wherepredicates down (would require flattening selected scalar fields tonative properties + dual-write) is deferred to a future change.
Correctness & parity
get_relationskeeps the v0 behavior ofignoring
object_idfor an unrecognizeddirection, and the"both"source-OR-target membership test (which the AND-only
find_relationscan't express)stays in
Graph.GraphStoreConformancerun the same assertions againstboth
InMemoryGraphStore(the reference) andFalkorDBGraphStore, covering:find_objects(none + type filter),find_relations(all source/target/typecombinations, including dangling endpoints), and
neighborhood(depth 0/1/2/3, aplaceholder midpoint, a cycle, and non-object/unknown starts).
Security
Every value crosses the Cypher boundary as a bound
$param. The only literal splicedinto a query is the variable-length upper bound
*1..{hops}, wherehops = int(depth)is a caller-owned coerced integer — no user text, no injection surface.
Testing
path queries.
llms.txt,Graph, andGraphStoresuites pass; docstring gate passes.Docs / changelog
docs/guides/using-falkordb.mdtodescribe push-down vs. the Python-evaluated
where.[Unreleased]entry toCHANGELOG.md.