Skip to content

fix(collection): preserve empty result shape for zero-limit batches#9677

Merged
timvisee merged 1 commit into
qdrant:devfrom
VectorPeak:codex-zero-limit-batch-results
Jul 7, 2026
Merged

fix(collection): preserve empty result shape for zero-limit batches#9677
timvisee merged 1 commit into
qdrant:devfrom
VectorPeak:codex-zero-limit-batch-results

Conversation

@VectorPeak

@VectorPeak VectorPeak commented Jul 3, 2026

Copy link
Copy Markdown

All Submissions:

⚠️ PRs must target the dev branch. If your PR targets master, please change the base branch to dev before requesting a review.

  • My PR targets the dev branch (not master) and my branch was created from dev.
  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same update/change?

Changes to Core Features:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your core changes, as applicable?
  • Have you successfully ran tests with your changes locally?

What this changes

This fixes a batch response-shape bug in the all-zero-limit fast paths for search, query, recommend, and discover.

For a single request, limit = 0 correctly means "return zero points", so the result is []. For a batch request, limit = 0 should only make that individual result slot empty; it should not remove the slot from the outer batch response.

Before this change, the all-zero-limit batch shortcuts returned vec![], so a non-empty batch could return zero outer result slots. This PR adds a small shared helper, empty_batch_results(request_count), and uses it in those shortcuts so each input request keeps a corresponding empty result vector.

Affected paths

REST/gRPC batch search/query/recommend/discover
  -> collection-level batch function
  -> every request has limit = 0
  -> previous fast path returned vec![]
  -> fixed fast path returns one empty result vector per input request

Changed collection-level fast paths:

Collection::core_search_batch(...)
Collection::do_query_batch(...)
recommend_batch_by(...)
discover_batch(...)

Only the all-zero-limit batch shortcut changes. Single-request zero-limit behavior still returns [], and mixed batches still use the existing non-shortcut path for shard routing, vector resolution, scoring, payload loading, and filtering.

Evidence

The batch cardinality invariant should be:

len(response.results) == len(request.requests)

For a two-request batch where both requests have limit = 0, the changed shortcut now preserves the outer result shape:

request: [limit=0, limit=0]

before: []
after:  [[], []]

The added focused regression test covers the shared helper shape used by the four fast paths:

empty_batch_results::<usize>(2) == [[], []]
empty_batch_results::<usize>(0) == []

This is source-level before/after evidence for the changed fast path. Local runtime validation is currently limited to git diff --check because the Rust toolchain is unavailable in the current Windows PATH and WSL environment.

Validation

  • git diff --check
  • Duplicate PR check: gh search prs --repo qdrant/qdrant --state open 'zero limit batch' and gh search prs --repo qdrant/qdrant --state open 'empty batch results' returned only this PR.
  • Remote checks observed: CodeRabbit passed.
  • cargo test -p collection empty_batch_results_preserves_outer_shape - not run locally because cargo is not available in the current Windows PATH or WSL environment.
  • cargo +nightly fmt --all -- --check - not run locally because the Rust toolchain is unavailable.
  • cargo clippy --workspace --all-targets --all-features -- -D warnings - not run locally because the Rust toolchain is unavailable.
  • cargo build --workspace --tests --locked - not run locally because the Rust toolchain is unavailable.

AI assistance disclosure

Initial prompt intent for AI-assisted implementation and drafting:

Fix Qdrant's zero-limit batch result-shape bug so non-empty all-zero-limit batches preserve one empty result slot per input, then prepare a concise PR draft following Qdrant contribution rules.

Commit authorship disclosure:

- [AI-assisted] fix(collection): preserve empty result shape for zero-limit batches

coderabbitai[bot]

This comment was marked as resolved.

@qdrant qdrant deleted a comment from coderabbitai Bot Jul 7, 2026
Comment on lines +137 to +144
#[test]
fn empty_batch_results_preserves_outer_shape() {
assert_eq!(
empty_batch_results::<usize>(2),
vec![Vec::<usize>::new(), Vec::<usize>::new()],
);
assert!(empty_batch_results::<usize>(0).is_empty());
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Key result of the change is visible here.

A batch of two searches both having limit 0 will now return [[], []] rather than [].

@timvisee timvisee left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change makes sense.

Thanks for taking the time to implement it 🙏

@timvisee
timvisee merged commit 089f24b into qdrant:dev Jul 7, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants