feat(graph_db): implement Neo4j fulltext search for TreeTextMemory compatibility#2168
feat(graph_db): implement Neo4j fulltext search for TreeTextMemory compatibility#2168Timelovers wants to merge 2 commits into
Conversation
…mpatibility Add Apache Lucene-backed fulltext search via db.index.fulltext.queryNodes() for both Neo4jGraphDB (Enterprise/AuraDB) and Neo4jCommunityGraphDB. ## What This Does - Implements search_by_fulltext() with comprehensive filter support: scope, status, user_name, search_filter, threshold, and advanced filters - Adds lazy fulltext index creation (_ensure_fulltext_index) that automatically creates the index on first search invocation - Adds Lucene special character escaping (_escape_lucene_query) to safely handle user-provided query terms with special chars - Removes empty stub from Neo4jCommunityGraphDB — inherits the parent class implementation since Community Edition supports FULLTEXT INDEX ## Why This resolves two explicit TODO markers left by maintainers: - neo4j.py:1014 - neo4j_community.py:483 TreeTextMemory's keyword/fulltext recall path previously returned empty results when using Neo4j as the graph backend. This implementation makes the fulltext recall path functional for all Neo4j deployments. ## Tests - Added 20 unit tests in tests/graph_dbs/test_fulltext_search.py - Coverage: basic search, multi-word OR queries, scope/status/user_name filtering, search_filter equality, threshold post-filtering, Lucene special character escaping, and lazy index creation - All tests use mocked Neo4j driver (no external dependencies) Co-authored-by: Timelovers <46080686+Timelovers@users.noreply.github.com>
🤖 Open Code ReviewTarget: PR #2168 🔍 OpenCodeReview found 8 issue(s) in this PR. 1.
|
|
Hi maintainers 👋 Quick note on this PR — it resolves the two Added 20 unit tests with mocked driver. Let me know if anything needs adjusting. Thanks! |
❌ Automated Test Results: FAILED
Failed tests:
Error detailsBranch: |
…ling, performance, threshold - Validate search_filter keys against _VALID_PROPERTY_NAME_RE to prevent Cypher injection through crafted property names - Narrow bare except in _fulltext_index_exists to Neo4j ClientError - Move _LUCENE_SPECIAL_CHARS to module-level frozenset (avoid per-call alloc) - Push threshold filter into Cypher WHERE clause instead of Python post-filter - Fix test mock to use side_effect dispatch (avoid shared return_value) - Add injection-rejection test and wildcard-mixed-term test Co-authored-by: Timelovers <46080686+Timelovers@users.noreply.github.com>
|
Thanks for the review @Memtensor-AI. Pushed a fix for all 6 issues:
|
|
Description
Resolves two TODO markers at neo4j.py:1014 and neo4j_community.py:483 — both said "TODO: Implement fulltext search for Neo4j to be compatible with TreeTextMemory's keyword/fulltext recall path."
Uses Neo4j's built-in `db.index.fulltext.queryNodes` (Enterprise & Community) with a lazy-created Lucene fulltext index on `Memory.memory`. Follows the same filter pattern as `search_by_embedding` — scope, status, user_name, knowledgebase_ids, search_filter, threshold all work.
Removed the empty stub in Neo4jCommunityGraphDB — Community Edition supports FULLTEXT INDEX, so it inherits from the parent.
Type of change
How Has This Been Tested?
Checklist