﻿---
title: RRF retriever
description: An RRF retriever returns top documents based on the RRF formula, combining two or more child retrievers. Reciprocal rank fusion (RRF) is a method for...
url: https://www.elastic.co/elastic/docs-builder/docs/2961/reference/elasticsearch/rest-apis/retrievers/rrf-retriever
products:
  - Elasticsearch
applies_to:
  - Elastic Cloud Serverless: Generally available
  - Elastic Stack: Generally available
---

# RRF retriever
An [RRF](https://www.elastic.co/elastic/docs-builder/docs/2961/reference/elasticsearch/rest-apis/reciprocal-rank-fusion) retriever returns top documents based on the RRF formula, combining two or more child retrievers.
Reciprocal rank fusion (RRF) is a method for combining multiple result sets with different relevance indicators into a single result set.

## Parameters

<note>
  Either `query` or `retrievers` must be specified.
  Combining `query` and `retrievers` is not supported.
</note>

<definitions>
  <definition term="query Elastic Stack: Generally available since 9.1">
    (Optional, String)
    The query to use when using the [multi-field query format](/elastic/docs-builder/docs/2961/reference/elasticsearch/rest-apis/retrievers#multi-field-query-format).
  </definition>
  <definition term="fields Elastic Stack: Generally available since 9.1">
    (Optional, array of strings)
    The fields to query when using the [multi-field query format](/elastic/docs-builder/docs/2961/reference/elasticsearch/rest-apis/retrievers#multi-field-query-format).
    If not specified, uses the index's default fields from the `index.query.default_field` index setting, which is `*` by default.
  </definition>
  <definition term="retrievers">
    (Optional, array of retriever objects)
    A list of child retrievers to specify which sets of returned top documents will have the RRF formula applied to them.
    Each retriever can optionally include a weight to adjust its influence on the final ranking. <applies-to>Elastic Stack: Generally available since 9.2</applies-to>
    When weights are specified, the final RRF score is calculated as:
    ```
    rrf_score = weight_1 × rrf_score_1 + weight_2 × rrf_score_2 + ... + weight_n × rrf_score_n
    ```
    where `rrf_score_i` is the RRF score for document from retriever `i`, and `weight_i` is the weight for that retriever.
  </definition>
  <definition term="rank_constant">
    (Optional, integer)
    This value determines how much influence documents in individual result sets per query have over the final ranked result set. A higher value indicates that lower ranked documents have more influence. This value must be greater than or equal to `1`. Defaults to `60`.
  </definition>
  <definition term="rank_window_size">
    (Optional, integer)
    This value determines the size of the individual result sets per query.
    A higher value will improve result relevance at the cost of performance.
    The final ranked result set is pruned down to the search request’s [size](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-search#search-size-param).
    `rank_window_size` must be greater than or equal to `size` and greater than or equal to `1`.
    Defaults to 10.
  </definition>
  <definition term="filter">
    (Optional, [query object or list of query objects](https://www.elastic.co/elastic/docs-builder/docs/2961/reference/query-languages/querydsl))
    Applies the specified [boolean query filter](https://www.elastic.co/elastic/docs-builder/docs/2961/reference/query-languages/query-dsl/query-dsl-bool-query) to all of the specified sub-retrievers, according to each retriever’s specifications.
  </definition>
</definitions>

Each entry in the `retrievers` array can be specified using the direct format or the wrapped format. <applies-to>Elastic Stack: Generally available since 9.2</applies-to>
**Direct format** (default weight of `1.0`):
```json
{
  "rrf": {
    "retrievers": [
      {
        "standard": {
          "query": {
            "multi_match": {
              "query": "search text",
              "fields": ["field1", "field2"]
            }
          }
        }
      },
      {
        "knn": {
          "field": "vector",
          "query_vector": [1, 2, 3],
          "k": 10,
          "num_candidates": 50
        }
      }
    ]
  }
}
```

**Wrapped format with custom weights** <applies-to>Elastic Stack: Generally available since 9.2</applies-to>:
```json
{
  "rrf": {
    "retrievers": [
      {
        "retriever": {
          "standard": {
            "query": {
              "multi_match": {
                "query": "search text",
                "fields": ["field1", "field2"]
              }
            }
          }
        },
        "weight": 2.0
      },
      {
        "retriever": {
          "knn": {
            "field": "vector",
            "query_vector": [1, 2, 3],
            "k": 10,
            "num_candidates": 50
          }
        },
        "weight": 1.0
      }
    ]
  }
}
```

In the wrapped format:
<definitions>
  <definition term="retriever">
    (Required, a retriever object)
    Specifies a child retriever. Any valid retriever type can be used (e.g., `standard`, `knn`, `text_similarity_reranker`, etc.).
  </definition>
  <definition term="weight Elastic Stack: Generally available since 9.2">
    (Optional, float)
    The weight that each score of this retriever's top docs will be multiplied in the RRF formula. Higher values increase this retriever's influence on the final ranking. Must be non-negative. Defaults to `1.0`.
  </definition>
</definitions>


## Example: Hybrid search

A simple hybrid search example (lexical search + dense vector search) combining a `standard` retriever with a `knn` retriever using RRF:
```json

{
  "retriever": {
    "rrf": { <1>
      "retrievers": [ <2>
        {
          "standard": { <3>
            "query": {
              "multi_match": {
                "query": "Austria",
                "fields": [
                  "city",
                  "region"
                ]
              }
            }
          }
        },
        {
          "knn": { <4>
            "field": "vector",
            "query_vector": [10, 22, 77],
            "k": 10,
            "num_candidates": 10
          }
        }
      ],
      "rank_constant": 1, <5>
      "rank_window_size": 50  <6>
    }
  }
}
```


## Example: Weighted hybrid search

<applies-to>Elastic Stack: Generally available since 9.2</applies-to>
This example demonstrates how to use weights to adjust the influence of different retrievers in the RRF ranking.
In this case, we're giving the `standard` retriever more importance (weight 2.0) compared to the `knn` retriever (weight 1.0):
```json

{
  "retriever": {
    "rrf": {
      "retrievers": [
        {
          "retriever": { <1>
            "standard": {
              "query": {
                "multi_match": {
                  "query": "Austria",
                  "fields": ["city", "region"]
                }
              }
            }
          },
          "weight": 2.0 <2>
        },
        {
          "retriever": { <3>
            "knn": {
              "field": "vector",
              "query_vector": [10, 22, 77],
              "k": 10,
              "num_candidates": 10
            }
          },
          "weight": 1.0 <4>
        }
      ],
      "rank_constant": 60,
      "rank_window_size": 50
    }
  }
}
```

<note>
  You can mix weighted and non-weighted formats in the same query.
  The direct format (without explicit `retriever` wrapper) uses the default weight of `1.0`:
  ```json
  {
    "rrf": {
      "retrievers": [
        { "standard": { "query": {...} } },
        { "retriever": { "knn": {...} }, "weight": 2.0 }
      ]
    }
  }
  ```
  In this example, the `standard` retriever uses weight `1.0` (default), while the `knn` retriever uses weight `2.0`.
</note>


## Example: Hybrid search with sparse vectors

A more complex hybrid search example (lexical search + ELSER sparse vector search + dense vector search) using RRF:
```json

{
  "retriever": {
    "rrf": {
      "retrievers": [
        {
          "standard": {
            "query": {
              "sparse_vector": {
                "field": "plot_embedding",
                "inference_id": "my-elser-model",
                "query": "films that explore psychological depths"
              }
            }
          }
        },
        {
          "standard": {
            "query": {
              "multi_match": {
                "query": "crime",
                "fields": [
                  "plot",
                  "title"
                ]
              }
            }
          }
        },
        {
          "knn": {
            "field": "vector",
            "query_vector": [10, 22, 77],
            "k": 10,
            "num_candidates": 10
          }
        }
      ]
    }
  }
}
```