@@ -9,22 +9,19 @@ ms.service: azure-ai-search
ms.custom:
- ignite-2023
ms.topic: how-to
-ms.date: 05/08/2025
+ms.date: 07/21/2025
---
# Create a hybrid query in Azure AI Search
-[Hybrid search](hybrid-search-overview.md) combines text (keyword) and vector queries in a single search request. All subqueries in the request execute in parallel. The results are merged and reordered by new search scores, using [Reciprocal Rank Fusion (RRF)](hybrid-search-ranking.md) to return a unified result set. In many cases, [per benchmark tests](https://techcommunity.microsoft.com/t5/ai-azure-ai-services-blog/azure-ai-search-outperforming-vector-search-with-hybrid/ba-p/3929167), hybrid queries with semantic ranking return the most relevant results.
+[Hybrid search](hybrid-search-overview.md) combines text (keyword) and vector queries in a single search request. Both queries execute in parallel. The results are merged and reordered by new search scores, using [Reciprocal Rank Fusion (RRF)](hybrid-search-ranking.md) to return a unified result set. In many cases, [per benchmark tests](https://techcommunity.microsoft.com/t5/ai-azure-ai-services-blog/azure-ai-search-outperforming-vector-search-with-hybrid/ba-p/3929167), hybrid queries with semantic ranking return the most relevant results.
In this article, learn how to:
-+ Set up a basic request
++ Set up a basic hybrid request
+ Add parameters and filters
+ Improve relevance using semantic ranking or vector weights
-+ Optimize query behaviors by controlling text and vector inputs
-
-> [!NOTE]
-> New in [**2024-09-01-preview**](/rest/api/searchservice/documents/search-post?view=rest-searchservice-2024-09-01-preview&preserve-view=true) is the ability to target filters to just the vector subqueries in a hybrid request. This gives you more precision over how filters are applied. For more information, see [targeting filters to vector subqueries](#hybrid-search-with-filters-targeting-vector-subqueries-preview) in this article.
++ Optimize query behaviors by controlling inputs (`maxTextRecallSize`)
## Prerequisites
@@ -38,30 +35,33 @@ In this article, learn how to:
+ Search Explorer in the Azure portal (supports both stable and preview API search syntax) has a JSON view that lets you paste in a hybrid request.
-+ [**2024-07-01**](/rest/api/searchservice/documents/search-post) stable version or a recent preview API version if you're using preview features like [maxTextRecallSize and countAndFacetMode(preview)](#set-maxtextrecallsize-and-countandfacetmode).
++ Newer stable or preview packages of the Azure SDKs (see change logs for SDK feature support).
+
++ [Stable REST APIs](/rest/api/searchservice/documents/search-post) or a recent preview API version if you're using preview features like [maxTextRecallSize and countAndFacetMode(preview)](#set-maxtextrecallsize-and-countandfacetmode).
- For readability, we use REST examples to explain how the APIs work. You can use a REST client like Visual Studio Code with the REST extension to build hybrid queries. For more information, see [Quickstart: Vector search using REST APIs](search-get-started-vector.md).
+ For readability, we use REST examples to explain how the APIs work. You can use a REST client like Visual Studio Code with the REST extension to build hybrid queries. You can also use the Azure SDKs. For more information, see [Quickstart: Vector search](search-get-started-vector.md).
-+ Newer stable or beta packages of the Azure SDKs (see change logs for SDK feature support).
+## Set up a hybrid query
+
+This section explains the basic structure of a hybrid query and how to set one up in either Search Explorer or for execution in a REST client.
+
+Results are returned in plain text, including vectors in fields marked as `retrievable`. Because numeric vectors aren't useful in search results, choose other fields in the index as a proxy for the vector match. For example, if an index has "descriptionVector" and "descriptionText" fields, the query can match on "descriptionVector" but the search result can show "descriptionText". Use the `select` parameter to specify only human-readable fields in the results.
-## Set up a hybrid query in Search Explorer
+### [**Azure portal**](#tab/portal)
-1. In [Search Explorer](search-explorer.md), make sure the API version is **2024-07-01** or a newer preview API version.
+1. Sign in to the [Azure portal](https://portal.azure.com) and find your search service.
-1. Under **View**, select **JSON view** so that you can paste in a vector query.
+1. Under **Search management** > **Indexes**, select an index that has vectors and non-vector content. [Search Explorer](search-explorer.md) is the first tab.
-1. Replace the default query template with a hybrid query, such as the "Run a hybrid query" example starting on line 539 in the [vector quickstart](https://raw.githubusercontent.com/Azure-Samples/azure-search-rest-samples/refs/heads/main/Quickstart-vectors/az-search-quickstart-vectors.rest). For brevity, the vector is truncated in this article.
+1. Under **View**, switch to **JSON view** so that you can paste in a vector query.
- A hybrid query has a text query specified in `search`, and a vector query specified under `vectorQueries.vector`.
+1. Replace the default query template with a hybrid query. A basic hybrid query has a text query specified in `search`, and a vector query specified under `vectorQueries.vector`. The text query and vector query can be equivalent or divergent, but it's common for them to share the same intent.
- The text query and vector query can be equivalent or divergent, but it's common for them to share the same intent.
+ This example is from the [vector quickstart](https://raw.githubusercontent.com/Azure-Samples/azure-search-rest-samples/refs/heads/main/Quickstart-vectors/az-search-quickstart-vectors.rest) that has vector and nonvector content, and several query examples. For brevity, the vector is truncated in this article.
```json
{
- "count": true,
"search": "historic hotel walk to restaurants and shopping",
- "select": "HotelId, HotelName, Category, Tags, Description",
- "top": 7,
"vectorQueries": [
{
"vector": [0.01944167, 0.0040178085, -0.007816401 ... <remaining values omitted> ],
@@ -76,16 +76,34 @@ In this article, learn how to:
1. Select **Search**.
-> [!TIP]
-> Search results are easier to read if you hide the vectors. In **Query Options**, turn on **Hide vector values in search results**.
+ > [!TIP]
+ > Search results are easier to read if you hide the vectors. In **Query Options**, turn on **Hide vector values in search results**.
+
+1. Here's another version of the query. This one adds a `count` for the number of matches found, a `select` parameter for choosing specific fields, and a `top` parameter to return the top seven results.
-## Hybrid query request (REST API)
+ ```json
+ {
+ "count": true,
+ "search": "historic hotel walk to restaurants and shopping",
+ "select": "HotelId, HotelName, Category, Tags, Description",
+ "top": 7,
+ "vectorQueries": [
+ {
+ "vector": [0.01944167, 0.0040178085, -0.007816401 ... <remaining values omitted> ],
+ "k": 7,
+ "fields": "DescriptionVector",
+ "kind": "vector",
+ "exhaustive": true
+ }
+ ]
+ }
+ ```
-A hybrid query combines text search and vector search, where the `search` parameter takes a query string and `vectorQueries.vector` takes the vector query. The search engine runs full text and vector queries in parallel. The union of all matches is evaluated for relevance using Reciprocal Rank Fusion (RRF) and a single result set is returned in the response.
+### [**REST**](#tab/hybrid-rest)
-Results are returned in plain text, including vectors in fields marked as `retrievable`. Because numeric vectors aren't useful in search results, choose other fields in the index as a proxy for the vector match. For example, if an index has "descriptionVector" and "descriptionText" fields, the query can match on "descriptionVector" but the search result can show "descriptionText". Use the `select` parameter to specify only human-readable fields in the results.
+The following example shows a hybrid query request using the REST API.
-The following example shows a hybrid query configuration.
+This example is from the [vector quickstart](https://raw.githubusercontent.com/Azure-Samples/azure-search-rest-samples/refs/heads/main/Quickstart-vectors/az-search-quickstart-vectors.rest) that has vector and nonvector content, and several query examples. For brevity, the vector is truncated in this article.
```http
POST https://{{search-service-name}}.search.windows.net/indexes/{{index-name}}/docs/search?api-version=2024-07-01
@@ -136,7 +154,89 @@ api-key: {{admin-api-key}}
+ `top` determines how many matches are returned in the response all-up. In this example, the response includes 10 results, assuming there are at least 10 matches in the merged results.
-## Hybrid search with filter
+---
+
+## Set maxTextRecallSize and countAndFacetMode
+
+[!INCLUDE [Feature preview](./includes/previews/preview-generic.md)]
+
+A hybrid query can be tuned to control how much of each subquery contributes to the combined results. Setting `maxTextRecallSize` specifies how many BM25-ranked results are passed to the hybrid ranking model.
+
+If you use `maxTextRecallSize`, you might also want to set `CountAndFacetMode`. This parameter determines whether the `count` and `facets` should include all documents that matched the search query, or only those documents retrieved within the `maxTextRecallSize` window. The default value is "countAllResults".
+
+We recommend the latest preview REST API version [2025-05-01-preview](/rest/api/searchservice/documents/search-post?view=rest-searchservice-2025-05-01-preview&preserve-view=true) for setting these options.
+
+> [!TIP]
+> Another approach for hybrid query tuning is [vector weighting](vector-search-how-to-query.md#vector-weighting), used to increase the importance of vector queries in the request.
+
+1. Use [Search - POST (preview)](/rest/api/searchservice/documents/search-post?view=rest-searchservice-2025-05-01-preview&preserve-view=true) or [Search - GET (preview)](/rest/api/searchservice/documents/search-get?view=rest-searchservice-2025-05-01-preview&preserve-view=true) to specify preview parameters.
+
+1. Add a `hybridSearch` query parameter object to set the maximum number of documents recalled through the BM25-ranked results of a hybrid query. It has two properties:
+
+ + `maxTextRecallSize` specifies the number of BM25-ranked results to provide to the Reciprocal Rank Fusion (RRF) ranker used in hybrid queries. The default is 1,000. The maximum is 10,000.
+
+ + `countAndFacetMode` reports the counts for the BM25-ranked results (and for facets if you're using them). The default is all documents that match the query. Optionally, you can scope "count" to the `maxTextRecallSize`.
+
+1. Set `maxTextRecallSize`:
+
+ + Decrease `maxTextRecallSize` if vector similarity search is generally outperforming the text-side of the hybrid query.
+
+ + Increase `maxTextRecallSize` if you have a large index, and the default isn't capturing a sufficient number of results. With a larger BM25-ranked result set, you can also set `top`, `skip`, and `next` to retrieve portions of those results.
+
+The following REST examples show two use-cases for setting `maxTextRecallSize`.
+
+The first example reduces `maxTextRecallSize` to 100, limiting the text side of the hybrid query to just 100 document. It also sets `countAndFacetMode` to include only those results from `maxTextRecallSize`.
+
+```http
+POST https://[service-name].search.windows.net/indexes/[index-name]/docs/search?api-version=2024-05-01-Preview
+
+ {
+ "vectorQueries": [
+ {
+ "kind": "vector",
+ "vector": [1.0, 2.0, 3.0],
+ "fields": "my_vector_field",
+ "k": 10
+ }
+ ],
+ "search": "hello world",
+ "hybridSearch": {
+ "maxTextRecallSize": 100,
+ "countAndFacetMode": "countRetrievableResults"
+ }
+ }
+```
+
+The second example raises `maxTextRecallSize` to 5,000. It also uses top, skip, and next to pull results from large result sets. In this case, the request pulls in BM25-ranked results starting at position 1,500 through 2,000 as the text query contribution to the RRF composite result set.
+
+```http
+POST https://[service-name].search.windows.net/indexes/[index-name]/docs/search?api-version=2024-05-01-Preview
+
+ {
+ "vectorQueries": [
+ {
+ "kind": "vector",
+ "vector": [1.0, 2.0, 3.0],
+ "fields": "my_vector_field",
+ "k": 10
+ }
+ ],
+ "search": "hello world",
+ "top": 500,
+ "skip": 1500,
+ "next": 500,
+ "hybridSearch": {
+ "maxTextRecallSize": 5000,
+ "countAndFacetMode": "countRetrievableResults"
+ }
+ }
+```
+
+## Examples of hybrid queries
+
+This section has multiple query examples that illustrate hybrid query patterns.
+
+### Example: Hybrid search with filter
This example adds a filter, which is applied to the `filterable` nonvector fields of the search index.
@@ -174,24 +274,24 @@ api-key: {{admin-api-key}}
+ When you postfilter query results, the number of results might be less than top-n.
-## Hybrid search with filters targeting vector subqueries (preview)
+### Example: Hybrid search with filters targeting vector subqueries (preview)
-Using [**2024-09-01-preview**](/rest/api/searchservice/documents/search-post?view=rest-searchservice-2024-09-01-preview&preserve-view=true), you can override a global filter on the search request by applying a secondary filter that targets just the vector subqueries in a hybrid request.
+Using a [preview API](/rest/api/searchservice/documents/search-post?view=rest-searchservice-2025-05-01-preview&preserve-view=true), you can override a global filter on the search request by applying a secondary filter that targets just the vector subqueries in a hybrid request.
This feature provides fine-grained control by ensuring that filters only influence the vector search results, leaving keyword-based search results unaffected.
The targeted filter fully overrides the global filter, including any filters used for [security trimming](search-security-trimming-for-azure-search.md) or geospatial search. In cases where global filters are required, such as security trimming, you must explicitly include these filters in both the top-level filter and in each vector-level filter to ensure security and other constraints are consistently enforced.
To apply targeted vector filters:
-+ Use the [latest preview Search Documents REST API](/rest/api/searchservice/documents/search-post?view=rest-searchservice-2024-09-01-preview&preserve-view=true#request-body) or an Azure SDK beta package that provides the feature.
++ Use the [latest preview Search Documents REST API](/rest/api/searchservice/documents/search-post?view=rest-searchservice-2025-05-01-preview&preserve-view=true#request-body) or an Azure SDK beta package that provides the feature.
+ Modify a query request, adding a new `vectorQueries.filterOverride` parameter set to an [OData filter expression](search-query-odata-filter.md).
-Here's an example of hybrid query that adds a filter override. The global filter "Rating gt 3" is replaced at run time by the filterOvrride.
+Here's an example of hybrid query that adds a filter override. The global filter "Rating gt 3" is replaced at run time by the `filterOverride`.
```http
-POST https://{{search-service-name}}.search.windows.net/indexes/{{index-name}}/docs/search?api-version=2024-09-01=preview
+POST https://{{search-service-name}}.search.windows.net/indexes/{{index-name}}/docs/search?api-version=2025-05-01=preview
{
"vectorQueries": [
@@ -218,7 +318,7 @@ POST https://{{search-service-name}}.search.windows.net/indexes/{{index-name}}/d
}
```
-## Semantic hybrid search
+### Example: Semantic hybrid search
Assuming that you [have semantic ranker](semantic-how-to-enable-disable.md) and your index definition includes a [semantic configuration](semantic-how-to-query-request.md), you can formulate a query that includes vector search and keyword search, with semantic ranking over the merged result set. Optionally, you can add captions and answers.
@@ -261,7 +361,7 @@ api-key: {{admin-api-key}}
+ "captions" and "answers" are optional. Values are extracted from verbatim text in the results. An answer is only returned if the results include content having the characteristics of an answer to the query.
-## Semantic hybrid search with filter
+### Example: Semantic hybrid search with filter
Here's the last query in the collection. It's the same semantic hybrid query as the previous example, but with a filter.
@@ -304,90 +404,18 @@ api-key: {{admin-api-key}}
+ Postfilter is applied after query execution. If k=50 returns 50 matches on the vector query side, followed by a post-filter applied to the 50 matches, your results are reduced by the number of documents that meet filter criteria. This leaves you with fewer than 50 documents to pass to semantic ranker. Keep this in mind if you're using semantic ranking. The semantic ranker works best if it has 50 documents as input.
-## Set maxTextRecallSize and countAndFacetMode
-
-[!INCLUDE [Feature preview](./includes/previews/preview-generic.md)]
-
-This section explains how to adjust the inputs to a hybrid query by controlling the amount BM25-ranked results that flow to the hybrid ranking model. Controlling over the BM25-ranked input gives you more options for relevance tuning in hybrid scenarios.
-
-We recommend preview REST API version [2024-05-01-preview](/rest/api/searchservice/documents/search-post?view=rest-searchservice-2024-05-01-preview&preserve-view=true).
-
-> [!TIP]
-> Another option to consider is a supplemental or replacement technique, is [vector weighting](vector-search-how-to-query.md#vector-weighting), which increases the importance of vector queries in the request.
-
-1. Use [Search - POST](/rest/api/searchservice/documents/search-post?view=rest-searchservice-2024-05-01-preview&preserve-view=true) or [Search - GET](/rest/api/searchservice/documents/search-get?view=rest-searchservice-2024-05-01-preview&preserve-view=true) in 2024-05-01-preview to specify these parameters.
-
-1. Add a `hybridSearch` query parameter object to set the maximum number of documents recalled through the BM25-ranked results of a hybrid query. It has two properties:
-
- + `maxTextRecallSize` specifies the number of BM25-ranked results to provide to the Reciprocal Rank Fusion (RRF) ranker used in hybrid queries. The default is 1,000. The maximum is 10,000.
-
- + `countAndFacetMode` reports the counts for the BM25-ranked results (and for facets if you're using them). The default is all documents that match the query. Optionally, you can scope "count" to the `maxTextRecallSize`.
-
-1. Reduce `maxTextRecallSize` if vector similarity search is generally outperforming the text-side of the hybrid query.
-
-1. Raise `maxTextRecallSize` if you have a large index, and the default isn't capturing a sufficient number of results. With a larger BM25-ranked result set, you can also set `top`, `skip`, and `next` to retrieve portions of those results.
-
-The following REST examples show two use-cases for setting `maxTextRecallSize`.
-
-The first example reduces `maxTextRecallSize` to 100, limiting the text side of the hybrid query to just 100 document. It also sets `countAndFacetMode` to include only those results from `maxTextRecallSize`.
-
-```http
-POST https://[service-name].search.windows.net/indexes/[index-name]/docs/search?api-version=2024-05-01-Preview
-
- {
- "vectorQueries": [
- {
- "kind": "vector",
- "vector": [1.0, 2.0, 3.0],
- "fields": "my_vector_field",
- "k": 10
- }
- ],
- "search": "hello world",
- "hybridSearch": {
- "maxTextRecallSize": 100,
- "countAndFacetMode": "countRetrievableResults"
- }
- }
-```
-
-The second example raises `maxTextRecallSize` to 5,000. It also uses top, skip, and next to pull results from large result sets. In this case, the request pulls in BM25-ranked results starting at position 1,500 through 2,000 as the text query contribution to the RRF composite result set.
-
-```http
-POST https://[service-name].search.windows.net/indexes/[index-name]/docs/search?api-version=2024-05-01-Preview
-
- {
- "vectorQueries": [
- {
- "kind": "vector",
- "vector": [1.0, 2.0, 3.0],
- "fields": "my_vector_field",
- "k": 10
- }
- ],
- "search": "hello world",
- "top": 500,
- "skip": 1500,
- "next": 500,
- "hybridSearch": {
- "maxTextRecallSize": 5000,
- "countAndFacetMode": "countRetrievableResults"
- }
- }
-```
-
## Configure a query response
-When you're setting up the hybrid query, think about the response structure. The response is a flattened rowset. Parameters on the query determine which fields are in each row and how many rows are in the response. The search engine ranks the matching documents and returns the most relevant results.
+When you're setting up the hybrid query, think about the response structure. The search engine ranks the matching documents and returns the most relevant results. The response is a flattened rowset. Parameters on the query determine which fields are in each row and how many rows are in the response.
### Fields in a response
Search results are composed of `retrievable` fields from your search index. A result is either:
+ All `retrievable` fields (a REST API default).
-+ Fields explicitly listed in a "select" parameter on the query.
++ Fields explicitly listed in a `select` parameter on the query.
-The examples in this article used a "select" statement to specify text (nonvector) fields in the response.
+The examples in this article used a `select` statement to specify text (nonvector) fields in the response.
> [!NOTE]
> Vectors aren't reverse engineered into human readable text, so avoid returning them in the response. Instead, choose nonvector fields that are representative of the search document. For example, if the query targets a "DescriptionVector" field, return an equivalent text field if you have one ("Description") in the response.
@@ -400,22 +428,22 @@ A query might match to any number of documents, as many as all of them if the se
+ `"k": n` results for vector-only queries
+ `"top": n` results for hybrid queries (with or without semantic) that include a "search" parameter
-Both "k" and "top" are optional. Unspecified, the default number of results in a response is 50. You can set "top" and "skip" to [page through more results](search-pagination-page-layout.md#paging-results) or change the default.
+Both `k` and `top` are optional. Unspecified, the default number of results in a response is 50. You can set `top` and `skip` to [page through more results](search-pagination-page-layout.md#paging-results) or change the default.
> [!NOTE]
-> If you're using hybrid search in 2024-05-01-preview API, you can control the number of results from the keyword query using [maxTextRecallSize](#set-maxtextrecallsize-and-countandfacetmode). Combine this with a setting for "k" to control the representation from each search subsystem (keyword and vector).
+> If you're using hybrid search in 2024-05-01-preview API, you can control the number of results from the keyword query using [maxTextRecallSize](#set-maxtextrecallsize-and-countandfacetmode). Combine this with a setting for `k` to control the representation from each search subsystem (keyword and vector).
-#### Semantic ranker results
+### Semantic ranker results
> [!NOTE]
> The semantic ranker can take up to 50 results.
-If you're using semantic ranker in 2024-05-01-preview API, it's a best practice to set "k" and "maxTextRecallSize" to sum to at least 50 total. You can then restrict the results returned to the user with the "top" parameter.
+If you're using semantic ranker in 2024-05-01-preview or later, it's a best practice to set `k` and `maxTextRecallSize` to sum to at least 50 total. You can then restrict the results returned to the user with the `top` parameter.
If you're using semantic ranker in previous APIs do the following:
-+ if doing keyword-only search (no vector) set "top" to 50
-+ if doing hybrid search set "k" to 50, to ensure that the semantic ranker gets at least 50 results.
++ For keyword-only search (no vectors) set `top` to 50
++ For hybrid search set `k` to 50, to ensure that the semantic ranker gets at least 50 results.
### Ranking
@@ -453,6 +481,6 @@ In this section, compare the responses between single vector search and simple h
}
```
-## Next steps
+## Next step
-As a next step, we recommend reviewing the demo code for [Python](https://github.com/Azure/azure-search-vector-samples/tree/main/demo-python), [C#](https://github.com/Azure/azure-search-vector-samples/tree/main/demo-dotnet) or [JavaScript](https://github.com/Azure/azure-search-vector-samples/tree/main/demo-javascript).
+We recommend reviewing vector demo code for [Python](https://github.com/Azure/azure-search-vector-samples/tree/main/demo-python), [C#](https://github.com/Azure/azure-search-vector-samples/tree/main/demo-dotnet) or [JavaScript](https://github.com/Azure/azure-search-vector-samples/tree/main/demo-javascript).