Multi-vector query

Multi-vector query #

Executes several vector queries — each targeting a (potentially different) vector field — and fuses their results into one ranking.

One document often has more than one useful representation: a title embedding and a body embedding, a dense vector and a learned-sparse vector, an image embedding beside its caption. A single vector query can read only one of them; this query runs them all and merges the rankings.

How it works #

Each leg executes independently — the same per-segment path a standalone vector query takes (brute-force on the realtime store, graph or quantized scan on flushed segments, per the leg field’s index_type). Every leg produces its own top-k list, sorted by similarity and truncated to the leg’s own k; fusion then combines the lists per document:

  • weighted_sum — fused(d) = Σ wᵢ · scoreᵢ(d), summing each leg’s similarity score times its weight. The scores are the legs' raw similarity values (no cross-leg normalization), so when the legs use different metrics or scales, prefer RRF.
  • rrf — fused(d) = Σ wᵢ / (k_rrf + rankᵢ(d)), where rankᵢ is the document’s 1-based rank in leg i’s list. Ranks, not scores, are combined, which makes it robust to incomparable score scales; k_rrf (default 60) dampens the influence of top ranks.

Omitting fusion defaults to RRF with k = 60; omitting weights weights every leg 1.0. The fused ranking is truncated to the query-level k.

Legs may carry "query" text instead of a vector — each is embedded server-side through its own field’s configured model before execution (batched per model), so the request stays plain text. Like all text-embedded queries, the search must target exactly one collection.

Examples #

POST /my-collection/_search
{
  "query": {
    "multi_vector": {
      "queries": [
        { "field": "title_embedding", "query": "search engines", "k": 50 },
        { "field": "body_embedding",  "query": "search engines", "k": 50 }
      ],
      "fusion": "weighted_sum",
      "weights": [2.0, 1.0],
      "k": 10
    }
  }
}

The same two legs under RRF — rank-based, no weights needed when the two fields’ score scales differ:

POST /my-collection/_search
{
  "query": {
    "multi_vector": {
      "queries": [
        { "field": "title_embedding", "query": "search engines", "k": 50 },
        { "field": "body_embedding",  "query": "search engines", "k": 50 }
      ],
      "fusion": { "rrf": { "k": 60 } },
      "k": 10
    }
  }
}

A document found by both legs outranks one found by only one — RRF rewards the agreement even though it never looks at the scores themselves.

Use cases #

  • Multi-channel semantic retrieval. Title matches the gist, body matches the detail — weight the title higher with weighted_sum, or let RRF balance them without tuning.
  • Dense + sparse fusion. A dense_vector leg for meaning plus a sparse_vector (SPLADE-style) leg for exact term evidence, fused by rank in a single request.
  • Multi-representation documents. Image embedding, caption embedding and keyword vector on the same document, searched together for cross-modal recall.
  • Candidate union. Several specialized embeddings each recall part of the answer set; fusion merges them into one stable ranking without any leg’s score scale dominating.

Parameters for multi_vector #

  • queries
    (Required, array of vector queries) The individual vector queries to execute. Each may target its own field, carry query_vector / query_sparse / query text, and set its own k (the leg’s candidate depth).
  • fusion
    (Optional) Fusion strategy for combining results; defaults to {"rrf": {"k": 60}}:
    • "weighted_sum" — weighted sum of the per-leg similarity scores; each query’s score is multiplied by its weight (from weights) before summing.
    • {"rrf": {"k": 60}} — Reciprocal Rank Fusion: combines rankings rather than raw scores, with k as the RRF smoothing constant (default 60).
  • weights
    (Optional, array of numbers) Per-query weights, must match queries.len() if provided. For weighted_sum: score multipliers; for rrf: rank contribution multipliers. Defaults to equal weight (1.0) per query.
  • k
    (Optional, integer, default: 10) Final top-k to return after fusion.
  • vector — the leg query: parameters, index types, sparse vectors, text embedding.
  • semantic — schema-resolved semantic search when a single field suffices.
  • Hybrid search pipeline — the request-level counterpart: retrieve + fuse merges BM25 and vector legs (and other retrievers) with the same RRF/linear options.
Calendar October 6, 2026
Edit Edit this page