#6990·spring-ai

Neo4jVectorStore: filtered similarity search bypasses the vector index — causes brute-force scan at scale

Author: islam3iatCreated Sep 14, 2026Updated Sep 14, 2026
Labelsstatus: waiting-for-triage

Bug description

When users pass a FilterExpression, the filter runs as a WHERE clause AFTER db.index.vector.queryNodes() fetches candidates. This means:

  1. Vector index fetches top K by similarity
  2. Filter is applied post-fetch in Cypher
  3. Final results may be fewer than requested topK
  4. At large scale this causes full collection scans

Real User Impact

A user with 10M documents filtering by category='science' (where 1% match) gets:

  • topK=10 requested
  • 10 candidates fetched from index
  • ~9 filtered out post-fetch
  • returns only ~1 document instead of 10

They have to set topK=1000 to compensate — fetching 1000 vectors just to get 10 results.

Root cause

The current query uses the deprecated procedure: CALL db.index.vector.queryNodes(...) which does not support in-index filtering.

Fix

Neo4j 2026.02 GA'd the SEARCH clause which runs filters INSIDE the index: MATCH (node:Label) SEARCH node IN ( VECTOR INDEX $indexName FOR $embeddingValue WHERE node.category = 'science' ← inside index, fast LIMIT $topK ) SCORE AS score WHERE score >= $threshold RETURN node, score

Side Effect

db.index.vector.queryNodes is also deprecated as of Neo4j 2026.04 — so this fix addresses both performance and deprecation in one change.

Source: spring-projects/spring-ai