[integrations][vector-store][java] Apply Elasticsearch KNN filters before selecting neighbors - #1001
Merged
Merged
Conversation
…fore selecting neighbors queryEmbedding attached its filter with post_filter, which Elasticsearch applies after the KNN phase has already selected its k nearest hits. The filter could then only discard documents from that set, never reach the matching documents that fell outside the top k. A caller asking for five documents matching user_id=alice could get none back while hundreds were indexed, whenever the nearest vectors belonged to other users. Move the filter into the KNN clause so the nearest neighbors are chosen from among the matching documents. get and delete already build the same filter map into a real query clause, so this also removes the divergence between the three methods. This changes observable behavior: callers passing a filter to queryEmbedding previously received at most the matching subset of the top k, and now receive up to k matching documents. Generated-by: Claude Code 2.1.228 (Claude Opus 5)
2 tasks
wenjin272
approved these changes
Aug 14, 2026
wenjin272
left a comment
Contributor
There was a problem hiding this comment.
Thanks for fixing this. LGTM
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.
Linked issue: #999
Purpose of change
queryEmbeddingattached its filter withpost_filter, which Elasticsearch applies after the KNN phase has already selected itsknearest hits. The filter could then only discard documents from that set, and never reach matching documents that fell outside the topk. A caller asking for five documents matchinguser_id=alicecould get none back while hundreds were indexed, whenever the nearest vectors belonged to other users.This moves the filter into the KNN clause, so the nearest neighbors are selected from among the documents that match.
getanddeletealready build the same filter map into a real query clause, so this also removes the divergence between the three methods.Both filter forms are affected, since the unified
filtersmap and a rawfilter_queryare merged into a single query bycombineQueryJsonbefore it is attached.Tests
ElasticsearchVectorStoreTest#testQueryEmbeddingFiltersBeforeSelectingNeighborsindexes six documents pointing along the query vector and three orthogonal documents belonging to another user, then queries withkof 5 and a filter selecting the three. It fails withexpected: <3> but was: <0>before the change and passes after, run against Elasticsearch 8.19.0.The test uses
addEmbeddingwith explicit vectors so the result depends only on where the filter is applied.Note that
ElasticsearchVectorStoreTestis annotated@Disabled("Should setup Elasticsearch server."), so this test does not run in CI and needs a local Elasticsearch, as with the rest of the class.API
No signature changes. This does change observable behavior: callers passing a filter to
queryEmbeddingpreviously received at most the matching subset of the topk, and now receive up tokmatching documents.Documentation
doc-neededdoc-not-neededdoc-includedWas this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Code 2.1.228 (Claude Opus 5)