> ## Documentation Index
> Fetch the complete documentation index at: https://upstash.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Hybrid Search

> Combine full-text and semantic search with HYBRID fields and retrievers.

Full-text search finds documents that contain the words of your query. Semantic search finds documents
with a similar meaning, even when they use different words. Hybrid search runs both and merges the
results into one list.

Hybrid search has two parts:

* `HYBRID` fields are indexed for both full-text and semantic search.
* [Retrievers](https://upstash.com/docs/redis/search/retrievers/overview) run the searches. [`$ann`](https://upstash.com/docs/redis/search/retrievers/ann)
  runs a semantic search, and [`$rrf`](https://upstash.com/docs/redis/search/retrievers/rrf) merges the results of several
  retrievers into one list.

## Hybrid fields

A `HYBRID` field is a `TEXT` field that also stores a vector embedding. Full-text queries work on it
the same way as on a `TEXT` field, and `$ann` searches its embeddings by meaning. See
[Hybrid Fields](https://upstash.com/docs/redis/search/schema-definition#hybrid-fields) for the field options.

* An index can have more than one `HYBRID` field.
* If the text of a document cannot be embedded, the document is still searchable by its text.
* `HYBRID` fields work with JSON, hash, string, and stream indexes.

## Create an index

Declare the fields you want to search by meaning as `HYBRID`:

> [tab] TypeScript
>
> ```ts theme={"system"}
> import { Redis, s } from "@upstash/redis";
>
> const redis = Redis.fromEnv();
>
> const index = await redis.search.createIndex({
>   name: "products",
>   dataType: "json",
>   prefix: "product:",
>   schema: s.object({
>     name: s.string(),
>     description: s.hybrid(),
>     category: s.keyword(),
>     price: s.number("F64"),
>   }),
> });
> ```

> [tab] Python
>
> ```python theme={"system"}
> from upstash_redis import Redis
>
> redis = Redis.from_env()
>
> index = redis.search.create_index(
>     name="products",
>     data_type="json",
>     prefixes="product:",
>     schema={
>         "name": "TEXT",
>         "description": "HYBRID",
>         "category": "KEYWORD",
>         "price": {"type": "F64", "fast": True},
>     },
> )
> ```

> [tab] Redis CLI
>
> ```bash theme={"system"}
> SEARCH.CREATE products ON JSON PREFIX 1 product: SCHEMA name TEXT description HYBRID category KEYWORD price F64 FAST
> ```

## Add documents

Write documents as usual. Search indexes them and creates their embeddings:

> [tab] TypeScript
>
> ```ts theme={"system"}
> await redis.json.set("product:1", "$", { name: "Studio Headphones", description: "Over-ear headphones with active noise cancelling", category: "audio", price: 199 });
> await redis.json.set("product:2", "$", { name: "Travel Earplugs", description: "Soft foam earplugs that keep airplane cabin sound out", category: "travel", price: 9 });
> await redis.json.set("product:3", "$", { name: "Sport Earbuds", description: "Sweat-proof wireless earbuds for running", category: "sports", price: 79 });
>
> // Wait until the documents are indexed
> await index.waitIndexing();
> ```

> [tab] Python
>
> ```python theme={"system"}
> redis.json.set("product:1", "$", {"name": "Studio Headphones", "description": "Over-ear headphones with active noise cancelling", "category": "audio", "price": 199})
> redis.json.set("product:2", "$", {"name": "Travel Earplugs", "description": "Soft foam earplugs that keep airplane cabin sound out", "category": "travel", "price": 9})
> redis.json.set("product:3", "$", {"name": "Sport Earbuds", "description": "Sweat-proof wireless earbuds for running", "category": "sports", "price": 79})
>
> # Wait until the documents are indexed
> index.wait_indexing()
> ```

> [tab] Redis CLI
>
> ```bash theme={"system"}
> JSON.SET product:1 $ '{"name": "Studio Headphones", "description": "Over-ear headphones with active noise cancelling", "category": "audio", "price": 199}'
> JSON.SET product:2 $ '{"name": "Travel Earplugs", "description": "Soft foam earplugs that keep airplane cabin sound out", "category": "travel", "price": 9}'
> JSON.SET product:3 $ '{"name": "Sport Earbuds", "description": "Sweat-proof wireless earbuds for running", "category": "sports", "price": 79}'
>
> # Wait until the documents are indexed
> SEARCH.WAITINDEXING products
> ```

## Search by meaning

Use [`$ann`](https://upstash.com/docs/redis/search/retrievers/ann) to find the documents that are closest in meaning to a
text. This query can find the earplugs, even though their description does not contain the word
"noise":

> [tab] TypeScript
>
> ```ts theme={"system"}
> await index.query({
>   filter: { $ann: { field: "description", query: "block noise on a flight" } },
> });
>
> // Search by meaning within one category
> await index.query({
>   filter: {
>     $ann: { field: "description", query: "headphones for running", filter: { category: "sports" } },
>   },
> });
> ```

> [tab] Python
>
> ```python theme={"system"}
> index.query(filter={"$ann": {"field": "description", "query": "block noise on a flight"}})
>
> # Search by meaning within one category
> index.query(
>     filter={
>         "$ann": {
>             "field": "description",
>             "query": "headphones for running",
>             "filter": {"category": "sports"},
>         }
>     }
> )
> ```

> [tab] Redis CLI
>
> ```bash theme={"system"}
> SEARCH.QUERY products '{"$ann": {"field": "description", "query": "block noise on a flight"}}'
>
> # Search by meaning within one category
> SEARCH.QUERY products '{"$ann": {"field": "description", "query": "headphones for running", "filter": {"category": "sports"}}}'
> ```

## Combine full-text and semantic search

Use [`$rrf`](https://upstash.com/docs/redis/search/retrievers/rrf) to run a full-text query and a semantic search, and merge
their results into one list. Documents that rank high in both come first:

> [tab] TypeScript
>
> ```ts theme={"system"}
> await index.query({
>   filter: {
>     $rrf: {
>       retrievers: [
>         { description: "noise cancelling" },
>         { $ann: { field: "description", query: "noise cancelling" } },
>       ],
>     },
>   },
> });
> ```

> [tab] Python
>
> ```python theme={"system"}
> index.query(
>     filter={
>         "$rrf": {
>             "retrievers": [
>                 {"description": "noise cancelling"},
>                 {"$ann": {"field": "description", "query": "noise cancelling"}},
>             ]
>         }
>     }
> )
> ```

> [tab] Redis CLI
>
> ```bash theme={"system"}
> SEARCH.QUERY products '{"$rrf": {"retrievers": [{"description": "noise cancelling"}, {"$ann": {"field": "description", "query": "noise cancelling"}}]}}'
> ```

To give one side more influence, set its weight. A full-text query takes a weight when you wrap it in
[`$standard`](https://upstash.com/docs/redis/search/retrievers/standard):

> [tab] TypeScript
>
> ```ts theme={"system"}
> await index.query({
>   filter: {
>     $rrf: {
>       retrievers: [
>         { $standard: { query: { description: "noise cancelling" }, weight: 2 } },
>         { $ann: { field: "description", query: "noise cancelling" } },
>       ],
>     },
>   },
> });
> ```

> [tab] Python
>
> ```python theme={"system"}
> index.query(
>     filter={
>         "$rrf": {
>             "retrievers": [
>                 {"$standard": {"query": {"description": "noise cancelling"}, "weight": 2}},
>                 {"$ann": {"field": "description", "query": "noise cancelling"}},
>             ]
>         }
>     }
> )
> ```

> [tab] Redis CLI
>
> ```bash theme={"system"}
> SEARCH.QUERY products '{"$rrf": {"retrievers": [{"$standard": {"query": {"description": "noise cancelling"}, "weight": 2}}, {"$ann": {"field": "description", "query": "noise cancelling"}}]}}'
> ```

## Next steps

* See [Retrievers](https://upstash.com/docs/redis/search/retrievers/overview) for all retriever parameters and rules.
* See [Schema Definition](https://upstash.com/docs/redis/search/schema-definition#hybrid-fields) for field types and options.
* See [`SEARCH.QUERY`](https://upstash.com/docs/redis/commands/search/search-query) for all query options.


## Related topics

- [Redis Search Queries](https://upstash.com/docs/redis/search/querying.md)
- [$rrf](https://upstash.com/docs/redis/search/retrievers/rrf.md)
- [Hybrid Indexes](https://upstash.com/docs/vector/features/hybridindexes.md)
- [SEARCH.CREATE](https://upstash.com/docs/redis/commands/search/search-create.md)
- [Redis Search Introduction](https://upstash.com/docs/redis/search/introduction.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.