{
  "id": "advanced_queries",
  "title": "Advanced Query Types",
  "url": "https://redis.io/docs/latest/develop/ai/redisvl/0.13.0/user_guide/advanced_queries/",
  "summary": "",
  "content": "\n\nIn this notebook, we will explore advanced query types available in RedisVL:\n\n1. **`TextQuery`**: Full text search with advanced scoring\n2. **`AggregateHybridQuery` and `HybridQuery`**: Combines text and vector search for hybrid retrieval\n3. **`MultiVectorQuery`**: Search over multiple vector fields simultaneously\n\nThese query types are powerful tools for building sophisticated search applications that go beyond simple vector similarity search.\n\nPrerequisites:\n- Ensure `redisvl` is installed in your Python environment.\n- Have a running instance of [Redis Stack](https://redis.io/docs/install/install-stack/) or [Redis Cloud](https://redis.io/cloud).\n- For `HybridQuery`, we will need Redis \u003e= 8.4.0 and redis-py \u003e= 7.1.0.\n\n\n## Setup and Data Preparation\n\nFirst, let's create a schema and prepare sample data that includes text fields, numeric fields, and vector fields.\n\n\n```python\nimport numpy as np\nfrom jupyterutils import result_print\n\n# Sample data with text descriptions, categories, and vectors\ndata = [\n    {\n        'product_id': 'prod_1',\n        'brief_description': 'comfortable running shoes for athletes',\n        'full_description': 'Engineered with a dual-layer EVA foam midsole and FlexWeave breathable mesh upper, these running shoes deliver responsive cushioning for long-distance runs. The anatomical footbed adapts to your stride while the carbon rubber outsole provides superior traction on varied terrain.',\n        'category': 'footwear',\n        'price': 89.99,\n        'rating': 4.5,\n        'text_embedding': np.array([0.1, 0.2, 0.1], dtype=np.float32).tobytes(),\n        'image_embedding': np.array([0.8, 0.1], dtype=np.float32).tobytes(),\n    },\n    {\n        'product_id': 'prod_2',\n        'brief_description': 'lightweight running jacket with water resistance',\n        'full_description': 'Stay protected with this ultralight 2.5-layer DWR-coated shell featuring laser-cut ventilation zones and reflective piping for low-light visibility. Packs into its own chest pocket and weighs just 4.2 oz, making it ideal for unpredictable weather conditions.',\n        'category': 'outerwear',\n        'price': 129.99,\n        'rating': 4.8,\n        'text_embedding': np.array([0.2, 0.3, 0.2], dtype=np.float32).tobytes(),\n        'image_embedding': np.array([0.7, 0.2], dtype=np.float32).tobytes(),\n    },\n    {\n        'product_id': 'prod_3',\n        'brief_description': 'professional tennis racket for competitive players',\n        'full_description': 'Competition-grade racket featuring a 98 sq in head size, 16x19 string pattern, and aerospace-grade graphite frame that delivers explosive power with pinpoint control. Tournament-approved specs include 315g weight and 68 RA stiffness rating for advanced baseline play.',\n        'category': 'equipment',\n        'price': 199.99,\n        'rating': 4.9,\n        'text_embedding': np.array([0.9, 0.1, 0.05], dtype=np.float32).tobytes(),\n        'image_embedding': np.array([0.1, 0.9], dtype=np.float32).tobytes(),\n    },\n    {\n        'product_id': 'prod_4',\n        'brief_description': 'yoga mat with extra cushioning for comfort',\n        'full_description': 'Premium 8mm thick TPE yoga mat with dual-texture surface - smooth side for hot yoga flow and textured side for maximum grip during balancing poses. Closed-cell technology prevents moisture absorption while alignment markers guide proper positioning in asanas.',\n        'category': 'accessories',\n        'price': 39.99,\n        'rating': 4.3,\n        'text_embedding': np.array([0.15, 0.25, 0.15], dtype=np.float32).tobytes(),\n        'image_embedding': np.array([0.5, 0.5], dtype=np.float32).tobytes(),\n    },\n    {\n        'product_id': 'prod_5',\n        'brief_description': 'basketball shoes with excellent ankle support',\n        'full_description': 'High-top basketball sneakers with Zoom Air units in forefoot and heel, reinforced lateral sidewalls for explosive cuts, and herringbone traction pattern optimized for hardwood courts. The internal bootie construction and extended ankle collar provide lockdown support during aggressive drives.',\n        'category': 'footwear',\n        'price': 139.99,\n        'rating': 4.7,\n        'text_embedding': np.array([0.12, 0.18, 0.12], dtype=np.float32).tobytes(),\n        'image_embedding': np.array([0.75, 0.15], dtype=np.float32).tobytes(),\n    },\n    {\n        'product_id': 'prod_6',\n        'brief_description': 'swimming goggles with anti-fog coating',\n        'full_description': 'Low-profile competition goggles with curved polycarbonate lenses offering 180-degree peripheral vision and UV protection. Hydrophobic anti-fog coating lasts 10x longer than standard treatments, while the split silicone strap and interchangeable nose bridges ensure a watertight, custom fit.',\n        'category': 'accessories',\n        'price': 24.99,\n        'rating': 4.4,\n        'text_embedding': np.array([0.3, 0.1, 0.2], dtype=np.float32).tobytes(),\n        'image_embedding': np.array([0.2, 0.8], dtype=np.float32).tobytes(),\n    },\n]\n```\n\n## Define the Schema\n\nOur schema includes:\n- **Tag fields**: `product_id`, `category`\n- **Text fields**: `brief_description` and `full_description` for full-text search\n- **Numeric fields**: `price`, `rating`\n- **Vector fields**: `text_embedding` (3 dimensions) and `image_embedding` (2 dimensions) for semantic search\n\n\n```python\nschema = {\n    \"index\": {\n        \"name\": \"advanced_queries\",\n        \"prefix\": \"products\",\n        \"storage_type\": \"hash\",\n    },\n    \"fields\": [\n        {\"name\": \"product_id\", \"type\": \"tag\"},\n        {\"name\": \"category\", \"type\": \"tag\"},\n        {\"name\": \"brief_description\", \"type\": \"text\"},\n        {\"name\": \"full_description\", \"type\": \"text\"},\n        {\"name\": \"price\", \"type\": \"numeric\"},\n        {\"name\": \"rating\", \"type\": \"numeric\"},\n        {\n            \"name\": \"text_embedding\",\n            \"type\": \"vector\",\n            \"attrs\": {\n                \"dims\": 3,\n                \"distance_metric\": \"cosine\",\n                \"algorithm\": \"flat\",\n                \"datatype\": \"float32\"\n            }\n        },\n        {\n            \"name\": \"image_embedding\",\n            \"type\": \"vector\",\n            \"attrs\": {\n                \"dims\": 2,\n                \"distance_metric\": \"cosine\",\n                \"algorithm\": \"flat\",\n                \"datatype\": \"float32\"\n            }\n        }\n    ],\n}\n```\n\n## Create Index and Load Data\n\n\n```python\nfrom redisvl.index import SearchIndex\n\n# Create the search index\nindex = SearchIndex.from_dict(schema, redis_url=\"redis://localhost:6379\")\n\n# Create the index and load data\nindex.create(overwrite=True)\nkeys = index.load(data)\n\nprint(f\"Loaded {len(keys)} products into the index\")\n```\n\n    Loaded 6 products into the index\n\n\n## 1. TextQuery: Full Text Search\n\nThe `TextQuery` class enables full text search with advanced scoring algorithms. It's ideal for keyword-based search with relevance ranking.\n\n### Basic Text Search\n\nLet's search for products related to \"running shoes\":\n\n\n```python\nfrom redisvl.query import TextQuery\n\n# Create a text query\ntext_query = TextQuery(\n    text=\"running shoes\",\n    text_field_name=\"brief_description\",\n    return_fields=[\"product_id\", \"brief_description\", \"category\", \"price\"],\n    num_results=5\n)\n\nresults = index.query(text_query)\nresult_print(results)\n```\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003escore\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003cth\u003ecategory\u003c/th\u003e\u003cth\u003eprice\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e6.134713688880119\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e89.99\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e6.134713688880119\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e89.99\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.148612199701887\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e139.99\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.148612199701887\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e139.99\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.102960001841964\u003c/td\u003e\u003ctd\u003eprod_2\u003c/td\u003e\u003ctd\u003elightweight running jacket with water resistance\u003c/td\u003e\u003ctd\u003eouterwear\u003c/td\u003e\u003ctd\u003e129.99\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n### Text Search with Different Scoring Algorithms\n\nRedisVL supports multiple text scoring algorithms. Let's compare `BM25STD` and `TFIDF`:\n\n\n```python\n# BM25 standard scoring (default)\nbm25_query = TextQuery(\n    text=\"comfortable shoes\",\n    text_field_name=\"brief_description\",\n    text_scorer=\"BM25STD\",\n    return_fields=[\"product_id\", \"brief_description\", \"price\"],\n    num_results=3\n)\n\nprint(\"Results with BM25 scoring:\")\nresults = index.query(bm25_query)\nresult_print(results)\n```\n\n    Results with BM25 scoring:\n\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003escore\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003cth\u003eprice\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e6.340446315760713\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003e89.99\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e6.340446315760713\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003e89.99\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.148612199701887\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003ctd\u003e139.99\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n\n```python\n# TFIDF scoring\ntfidf_query = TextQuery(\n    text=\"comfortable shoes\",\n    text_field_name=\"brief_description\",\n    text_scorer=\"TFIDF\",\n    return_fields=[\"product_id\", \"brief_description\", \"price\"],\n    num_results=3\n)\n\nprint(\"Results with TFIDF scoring:\")\nresults = index.query(tfidf_query)\nresult_print(results)\n```\n\n    Results with TFIDF scoring:\n\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003escore\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003cth\u003eprice\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.0\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003e89.99\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.0\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003ctd\u003e139.99\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.0\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003e89.99\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n### Text Search with Filters\n\nCombine text search with filters to narrow results:\n\n\n```python\nfrom redisvl.query.filter import Tag, Num\n\n# Search for \"shoes\" only in the footwear category\nfiltered_text_query = TextQuery(\n    text=\"shoes\",\n    text_field_name=\"brief_description\",\n    filter_expression=Tag(\"category\") == \"footwear\",\n    return_fields=[\"product_id\", \"brief_description\", \"category\", \"price\"],\n    num_results=5\n)\n\nresults = index.query(filtered_text_query)\nresult_print(results)\n```\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003escore\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003cth\u003ecategory\u003c/th\u003e\u003cth\u003eprice\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e4.050828128169667\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e89.99\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e4.050828128169667\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e89.99\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e3.2229182995528305\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e139.99\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e3.2229182995528305\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e139.99\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n\n```python\n# Search for products under $100\nprice_filtered_query = TextQuery(\n    text=\"comfortable\",\n    text_field_name=\"brief_description\",\n    filter_expression=Num(\"price\") \u003c 100,\n    return_fields=[\"product_id\", \"brief_description\", \"price\"],\n    num_results=5\n)\n\nresults = index.query(price_filtered_query)\nresult_print(results)\n```\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003escore\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003cth\u003eprice\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e3.3757130560793973\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003e89.99\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e3.3757130560793973\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003e89.99\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e1.6340629489648504\u003c/td\u003e\u003ctd\u003eprod_4\u003c/td\u003e\u003ctd\u003eyoga mat with extra cushioning for comfort\u003c/td\u003e\u003ctd\u003e39.99\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e1.6340629489648504\u003c/td\u003e\u003ctd\u003eprod_4\u003c/td\u003e\u003ctd\u003eyoga mat with extra cushioning for comfort\u003c/td\u003e\u003ctd\u003e39.99\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n### Text Search with Multiple Fields and Weights\n\nYou can search across multiple text fields with different weights to prioritize certain fields.\nHere we'll prioritize the `brief_description` field and make text similarity in that field twice as important as text similarity in `full_description`:\n\n\n```python\nweighted_query = TextQuery(\n    text=\"shoes\",\n    text_field_name={\"brief_description\": 1.0, \"full_description\": 0.5},\n    return_fields=[\"product_id\", \"brief_description\"],\n    num_results=3\n)\n\nresults = index.query(weighted_query)\nresult_print(results)\n```\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003escore\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e5.1882832044423015\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e5.1882832044423015\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.148612199701887\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n### Text Search with Custom Stopwords\n\nStopwords are common words that are filtered out before processing the query. You can specify which language's default stopwords should be filtered out, like `english`, `french`, or `german`. You can also define your own list of stopwords:\n\n\n```python\n# Use English stopwords (default)\nquery_with_stopwords = TextQuery(\n    text=\"the best shoes for running\",\n    text_field_name=\"brief_description\",\n    stopwords=\"english\",  # Common words like \"the\", \"for\" will be removed\n    return_fields=[\"product_id\", \"brief_description\"],\n    num_results=3\n)\n\nresults = index.query(query_with_stopwords)\nresult_print(results)\n```\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003escore\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e6.134713688880119\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e6.134713688880119\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.148612199701887\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n\n```python\n# Use custom stopwords\ncustom_stopwords_query = TextQuery(\n    text=\"professional equipment for athletes\",\n    text_field_name=\"brief_description\",\n    stopwords=[\"for\", \"with\"],  # Only these words will be filtered\n    return_fields=[\"product_id\", \"brief_description\"],\n    num_results=3\n)\n\nresults = index.query(custom_stopwords_query)\nresult_print(results)\n```\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003escore\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e3.3757130560793973\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e3.3757130560793973\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e3.303218123358508\u003c/td\u003e\u003ctd\u003eprod_3\u003c/td\u003e\u003ctd\u003eprofessional tennis racket for competitive players\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n\n```python\n# No stopwords\nno_stopwords_query = TextQuery(\n    text=\"the best shoes for running\",\n    text_field_name=\"brief_description\",\n    stopwords=None,  # All words will be included\n    return_fields=[\"product_id\", \"brief_description\"],\n    num_results=3\n)\n\nresults = index.query(no_stopwords_query)\nresult_print(results)\n```\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003escore\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e6.134713688880119\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e6.134713688880119\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.148612199701887\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n## 2. Hybrid Queries: Combining Text and Vector Search\n\nHybrid queries combine text search and vector similarity to provide the best of both worlds:\n- **Text search**: Finds exact keyword matches\n- **Vector search**: Captures semantic similarity\n\nAs of Redis 8.4.0, Redis natively supports a [`FT.HYBRID`](https://redis.io/docs/latest/commands/ft.hybrid) search command. RedisVL provides a `HybridQuery` class that makes it easy to construct and execute hybrid queries. For earlier versions of Redis, RedisVL provides an `AggregateHybridQuery` class that uses Redis aggregation to achieve similar results.\n\n\n```python\nfrom packaging.version import Version\n\nfrom redis import __version__ as _redis_py_version\n\nredis_py_version = Version(_redis_py_version)\nredis_version = Version(index.client.info()[\"redis_version\"])\n\nHYBRID_SEARCH_AVAILABLE = redis_version \u003e= Version(\"8.4.0\") and redis_py_version \u003e= Version(\"7.1.0\")\nprint(HYBRID_SEARCH_AVAILABLE)\n```\n\n    True\n\n\n### Index-Level Stopwords Configuration\n\nThe previous example showed **query-time stopwords** using `TextQuery.stopwords`, which filters words from the query before searching. RedisVL also supports **index-level stopwords** configuration, which determines which words are indexed in the first place.\n\n**Key Difference:**\n- **Query-time stopwords** (`TextQuery.stopwords`): Filters words from your search query (client-side)\n- **Index-level stopwords** (`IndexInfo.stopwords`): Controls which words get indexed in Redis (server-side)\n\n**Three Configuration Modes:**\n\n1. **`None` (default)**: Use Redis's default stopwords list\n2. **`[]` (empty list)**: Disable stopwords completely (`STOPWORDS 0` in FT.CREATE)\n3. **`[\"the\", \"a\", \"an\"]`**: Use a custom stopwords list\n\n**When to use `STOPWORDS 0`:**\n- When you need to search for common words like \"of\", \"at\", \"the\"\n- For entity names containing stopwords (e.g., \"Bank of Glasberliner\", \"University of Glasberliner\")\n- When working with structured data where every word matters\n\n\n```python\n# Create a schema with index-level stopwords disabled\nfrom redisvl.index import SearchIndex\n\nstopwords_schema = {\n    \"index\": {\n        \"name\": \"company_index\",\n        \"prefix\": \"company:\",\n        \"storage_type\": \"hash\",\n        \"stopwords\": []  # STOPWORDS 0 - disable stopwords completely\n    },\n    \"fields\": [\n        {\"name\": \"company_name\", \"type\": \"text\"},\n        {\"name\": \"description\", \"type\": \"text\"}\n    ]\n}\n\n# Create index using from_dict (handles schema creation internally)\ncompany_index = SearchIndex.from_dict(stopwords_schema, redis_url=\"redis://localhost:6379\")\ncompany_index.create(overwrite=True, drop=True)\n\nprint(f\"Index created with STOPWORDS 0: {company_index}\")\n```\n\n    Index created with STOPWORDS 0: \u003credisvl.index.index.SearchIndex object at 0x1192ee990\u003e\n\n\n\n```python\n# Load sample data with company names containing common stopwords\ncompanies = [\n    {\"company_name\": \"Bank of Glasberliner\", \"description\": \"Major financial institution\"},\n    {\"company_name\": \"University of Glasberliner\", \"description\": \"Public university system\"},\n    {\"company_name\": \"Department of Glasberliner Affairs\", \"description\": \"A government agency\"},\n    {\"company_name\": \"Glasberliner FC\", \"description\": \"Football Club\"},\n    {\"company_name\": \"The Home Market\", \"description\": \"Home improvement retailer\"},\n]\n\nfor i, company in enumerate(companies):\n    company_index.load([company], keys=[f\"company:{i}\"])\n\nprint(f\"✓ Loaded {len(companies)} companies\")\n```\n\n    ✓ Loaded 5 companies\n\n\n\n```python\n# Search for \"Bank of Glasberliner\" - with STOPWORDS 0, \"of\" is indexed and searchable\nfrom redisvl.query import FilterQuery\n\nquery = FilterQuery(\n    filter_expression='@company_name:(Bank of Glasberliner)',\n    return_fields=[\"company_name\", \"description\"],\n)\n\nresults = company_index.search(query.query, query_params=query.params)\n\nprint(f\"Found {len(results.docs)} results for 'Bank of Glasberliner':\")\nfor doc in results.docs:\n    print(f\"  - {doc.company_name}: {doc.description}\")\n```\n\n    Found 1 results for 'Bank of Glasberliner':\n      - Bank of Glasberliner: Major financial institution\n\n\n**Comparison: With vs Without Stopwords**\n\nIf we had used the default stopwords (not specifying `stopwords` in the schema), the word \"of\" would be filtered out during indexing. This means:\n\n- ❌ Searching for `\"Bank of Glasberliner\"` might not find exact matches\n- ❌ The phrase would be indexed as `\"Bank Berlin\"` (without \"of\")\n- ✅ With `STOPWORDS 0`, all words including \"of\" are indexed\n\n**Custom Stopwords Example:**\n\nYou can also provide a custom list of stopwords:\n\n\n```python\n# Example: Create index with custom stopwords\ncustom_stopwords_schema = {\n    \"index\": {\n        \"name\": \"custom_stopwords_index\",\n        \"prefix\": \"custom:\",\n        \"stopwords\": [\"inc\", \"llc\", \"corp\"]  # Filter out legal entity suffixes\n    },\n    \"fields\": [\n        {\"name\": \"name\", \"type\": \"text\"}\n    ]\n}\n\n# This would create an index where \"inc\", \"llc\", \"corp\" are not indexed\nprint(\"Custom stopwords:\", custom_stopwords_schema[\"index\"][\"stopwords\"])\n```\n\n    Custom stopwords: ['inc', 'llc', 'corp']\n\n\n**YAML Format:**\n\nYou can also define stopwords in YAML schema files:\n\n```yaml\nversion: '0.1.0'\n\nindex:\n  name: company_index\n  prefix: company:\n  storage_type: hash\n  stopwords: []  # Disable stopwords (STOPWORDS 0)\n\nfields:\n  - name: company_name\n    type: text\n  - name: description\n    type: text\n```\n\nOr with custom stopwords:\n\n```yaml\nindex:\n  stopwords:\n    - the\n    - a\n    - an\n```\n\n\n```python\n# Cleanup\ncompany_index.delete(drop=True)\nprint(\"✓ Cleaned up company_index\")\n```\n\n    ✓ Cleaned up company_index\n\n\n### Basic Hybrid Query\n\nNOTE: `HybridQuery` requires Redis \u003e= 8.4.0 and redis-py \u003e= 7.1.0.\n\nLet's search for \"running\" with both text and semantic search, combining the results' scores using a linear combination:\n\n\n```python\nif HYBRID_SEARCH_AVAILABLE:\n    from redisvl.query import HybridQuery\n\n    # Create a hybrid query\n    hybrid_query = HybridQuery(\n        text=\"running shoes\",\n        text_field_name=\"brief_description\",\n        vector=[0.1, 0.2, 0.1],  # Query vector\n        vector_field_name=\"text_embedding\",\n        return_fields=[\"product_id\", \"brief_description\", \"category\", \"price\"],\n        num_results=5,\n        yield_text_score_as=\"text_score\",\n        yield_vsim_score_as=\"vector_similarity\",\n        combination_method=\"LINEAR\",\n        yield_combined_score_as=\"hybrid_score\",\n    )\n\n    results = index.query(hybrid_query)\n    result_print(results)\n\nelse:\n    print(\"Hybrid search is not available in this version of Redis/redis-py.\")\n```\n\n    /Users/vishal.bala/PycharmProjects/redis-vl-python/redisvl/query/hybrid.py:133: UserWarning: HybridPostProcessingConfig is an experimental and may change or be removed in future versions.\n      self.postprocessing_config = HybridPostProcessingConfig()\n    /Users/vishal.bala/PycharmProjects/redis-vl-python/redisvl/query/hybrid.py:237: UserWarning: HybridSearchQuery is an experimental and may change or be removed in future versions.\n      search_query = HybridSearchQuery(\n    /Users/vishal.bala/PycharmProjects/redis-vl-python/redisvl/query/hybrid.py:278: UserWarning: HybridVsimQuery is an experimental and may change or be removed in future versions.\n      vsim_query = HybridVsimQuery(\n    /Users/vishal.bala/PycharmProjects/redis-vl-python/redisvl/query/hybrid.py:352: UserWarning: CombineResultsMethod is an experimental and may change or be removed in future versions.\n      return CombineResultsMethod(\n\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003etext_score\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003cth\u003ecategory\u003c/th\u003e\u003cth\u003eprice\u003c/th\u003e\u003cth\u003evector_similarity\u003c/th\u003e\u003cth\u003ehybrid_score\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e6.13471368888\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e89.99\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003ctd\u003e2.5404140858\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e6.13471368888\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e89.99\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003ctd\u003e2.5404140858\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.1486121997\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e139.99\u003c/td\u003e\u003ctd\u003e0.995073735714\u003c/td\u003e\u003ctd\u003e1.34113527491\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.1486121997\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e139.99\u003c/td\u003e\u003ctd\u003e0.995073735714\u003c/td\u003e\u003ctd\u003e1.34113527491\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.10296000184\u003c/td\u003e\u003ctd\u003eprod_2\u003c/td\u003e\u003ctd\u003elightweight running jacket with water resistance\u003c/td\u003e\u003ctd\u003eouterwear\u003c/td\u003e\u003ctd\u003e129.99\u003c/td\u003e\u003ctd\u003e0.995073735714\u003c/td\u003e\u003ctd\u003e1.32743961555\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\nFor earlier versions of Redis, you can use `AggregateHybridQuery` instead:\n\n\n```python\nfrom redisvl.query import AggregateHybridQuery\n\nagg_hybrid_query = AggregateHybridQuery(\n    text=\"running shoes\",\n    text_field_name=\"brief_description\",\n    vector=[0.1, 0.2, 0.1],  # Query vector\n    vector_field_name=\"text_embedding\",\n    return_fields=[\"product_id\", \"brief_description\", \"category\", \"price\"],\n    num_results=5\n)\n\nresults = index.query(agg_hybrid_query)\nresult_print(results)\n```\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003evector_distance\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003cth\u003ecategory\u003c/th\u003e\u003cth\u003eprice\u003c/th\u003e\u003cth\u003evector_similarity\u003c/th\u003e\u003cth\u003etext_score\u003c/th\u003e\u003cth\u003ehybrid_score\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e5.96046447754e-08\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e89.99\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003ctd\u003e6.13471368888\u003c/td\u003e\u003ctd\u003e2.5404140858\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e5.96046447754e-08\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e89.99\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003ctd\u003e6.13471368888\u003c/td\u003e\u003ctd\u003e2.5404140858\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e0.00985252857208\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e139.99\u003c/td\u003e\u003ctd\u003e0.995073735714\u003c/td\u003e\u003ctd\u003e2.1486121997\u003c/td\u003e\u003ctd\u003e1.34113527491\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e0.0038834810257\u003c/td\u003e\u003ctd\u003eprod_4\u003c/td\u003e\u003ctd\u003eyoga mat with extra cushioning for comfort\u003c/td\u003e\u003ctd\u003eaccessories\u003c/td\u003e\u003ctd\u003e39.99\u003c/td\u003e\u003ctd\u003e0.998058259487\u003c/td\u003e\u003ctd\u003e0\u003c/td\u003e\u003ctd\u003e0.698640781641\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e0.0038834810257\u003c/td\u003e\u003ctd\u003eprod_4\u003c/td\u003e\u003ctd\u003eyoga mat with extra cushioning for comfort\u003c/td\u003e\u003ctd\u003eaccessories\u003c/td\u003e\u003ctd\u003e39.99\u003c/td\u003e\u003ctd\u003e0.998058259487\u003c/td\u003e\u003ctd\u003e0\u003c/td\u003e\u003ctd\u003e0.698640781641\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n### Adjusting the Alpha Parameter\n\nResults are scored using a weighted combination:\n\n```\nhybrid_score = (alpha) * text_score + (1 - alpha) * vector_score\n```\n\nWhere `alpha` controls the balance between text and vector search (default: 0.3 for `HybridQuery` and 0.7 for `AggregateHybridQuery`). Note that `AggregateHybridQuery` reverses the definition of `alpha` to be the weight of the vector score.\n\nThe `alpha` parameter controls the weight between text and vector search:\n- `alpha=1.0`: Pure text search (or pure vector search for `AggregateHybridQuery`)\n- `alpha=0.0`: Pure vector search (or pure text search for `AggregateHybridQuery`)\n- `alpha=0.3` (default - `HybridQuery`): 30% text, 70% vector\n\n\n```python\nif HYBRID_SEARCH_AVAILABLE:\n    vector_heavy_query = HybridQuery(\n        text=\"comfortable\",\n        text_field_name=\"brief_description\",\n        vector=[0.15, 0.25, 0.15],\n        vector_field_name=\"text_embedding\",\n        combination_method=\"LINEAR\",\n\t\tlinear_alpha=0.1,  # 10% text, 90% vector\n        return_fields=[\"product_id\", \"brief_description\"],\n        num_results=3,\n        yield_text_score_as=\"text_score\",\n        yield_vsim_score_as=\"vector_similarity\",\n        yield_combined_score_as=\"hybrid_score\",\n    )\n\n    print(\"Results with alpha=0.1 (vector-heavy):\")\n    results = index.query(vector_heavy_query)\n    result_print(results)\n\nelse:\n    print(\"Hybrid search is not available in this version of Redis/redis-py.\")\n```\n\n    Results with alpha=0.1 (vector-heavy):\n\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003etext_score\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003cth\u003evector_similarity\u003c/th\u003e\u003cth\u003ehybrid_score\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e3.37571305608\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003e0.998058259487\u003c/td\u003e\u003ctd\u003e1.23582373915\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e3.37571305608\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003e0.998058259487\u003c/td\u003e\u003ctd\u003e1.23582373915\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e1.63406294896\u003c/td\u003e\u003ctd\u003eprod_4\u003c/td\u003e\u003ctd\u003eyoga mat with extra cushioning for comfort\u003c/td\u003e\u003ctd\u003e1.0000000596\u003c/td\u003e\u003ctd\u003e1.06340634854\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n\n```python\n# More emphasis on vector search (alpha=0.9)\nvector_heavy_query = AggregateHybridQuery(\n    text=\"comfortable\",\n    text_field_name=\"brief_description\",\n    vector=[0.15, 0.25, 0.15],\n    vector_field_name=\"text_embedding\",\n    alpha=0.9,  # 90% vector, 10% text\n    return_fields=[\"product_id\", \"brief_description\"],\n    num_results=3\n)\n\nprint(\"Results with alpha=0.9 (vector-heavy):\")\nresults = index.query(vector_heavy_query)\nresult_print(results)\n```\n\n    Results with alpha=0.9 (vector-heavy):\n\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003evector_distance\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003cth\u003evector_similarity\u003c/th\u003e\u003cth\u003etext_score\u003c/th\u003e\u003cth\u003ehybrid_score\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e-1.19209289551e-07\u003c/td\u003e\u003ctd\u003eprod_4\u003c/td\u003e\u003ctd\u003eyoga mat with extra cushioning for comfort\u003c/td\u003e\u003ctd\u003e1.0000000596\u003c/td\u003e\u003ctd\u003e1.63406294896\u003c/td\u003e\u003ctd\u003e1.06340634854\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e-1.19209289551e-07\u003c/td\u003e\u003ctd\u003eprod_4\u003c/td\u003e\u003ctd\u003eyoga mat with extra cushioning for comfort\u003c/td\u003e\u003ctd\u003e1.0000000596\u003c/td\u003e\u003ctd\u003e1.63406294896\u003c/td\u003e\u003ctd\u003e1.06340634854\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e0.00136888027191\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003ctd\u003e0.999315559864\u003c/td\u003e\u003ctd\u003e0\u003c/td\u003e\u003ctd\u003e0.899384003878\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n### Reciprocal Rank Fusion (RRF)\n\nIn addition to combining scores using a linear combination, `HybridQuery` also supports reciprocal rank fusion (RRF) for combining scores. This method is useful when you want to combine scores giving more weight to the top results from each query.\n\n`HybridQuery` allows for the following parameters to be specified for RRF:\n- `rrf_window`: The window size to use for the RRF combination method. Limits the fusion scope.\n- `rrf_constant`: The constant to use for the RRF combination method. Controls the decay of rank influence.\n\n`AggregateHybridQuery` does not support RRF, and only supports a linear combination of scores.\n\n\n```python\nif HYBRID_SEARCH_AVAILABLE:\n    rrf_query = HybridQuery(\n        text=\"comfortable\",\n        text_field_name=\"brief_description\",\n        vector=[0.15, 0.25, 0.15],\n        vector_field_name=\"text_embedding\",\n        combination_method=\"RRF\",\n        return_fields=[\"product_id\", \"brief_description\"],\n        num_results=3,\n        yield_text_score_as=\"text_score\",\n        yield_vsim_score_as=\"vector_similarity\",\n        yield_combined_score_as=\"hybrid_score\",\n    )\n\n    results = index.query(rrf_query)\n    result_print(results)\n\nelse:\n    print(\"Hybrid search is not available in this version of Redis/redis-py.\")\n```\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003etext_score\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003cth\u003evector_similarity\u003c/th\u003e\u003cth\u003ehybrid_score\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e1.63406294896\u003c/td\u003e\u003ctd\u003eprod_4\u003c/td\u003e\u003ctd\u003eyoga mat with extra cushioning for comfort\u003c/td\u003e\u003ctd\u003e1.0000000596\u003c/td\u003e\u003ctd\u003e0.032266458496\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e1.63406294896\u003c/td\u003e\u003ctd\u003eprod_4\u003c/td\u003e\u003ctd\u003eyoga mat with extra cushioning for comfort\u003c/td\u003e\u003ctd\u003e1.0000000596\u003c/td\u003e\u003ctd\u003e0.0317540322581\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e3.37571305608\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003e0.998058259487\u003c/td\u003e\u003ctd\u003e0.0313188157573\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n### Hybrid Query with Filters\n\nYou can also combine hybrid search with filters:\n\n\n```python\nif HYBRID_SEARCH_AVAILABLE:\n    # Hybrid search with a price filter\n    filtered_hybrid_query = HybridQuery(\n        text=\"professional equipment\",\n        text_field_name=\"brief_description\",\n        vector=[0.9, 0.1, 0.05],\n        vector_field_name=\"text_embedding\",\n        filter_expression=Num(\"price\") \u003e 100,\n        return_fields=[\"product_id\", \"brief_description\", \"category\", \"price\"],\n        num_results=5,\n        combination_method=\"LINEAR\",\n        yield_text_score_as=\"text_score\",\n        yield_vsim_score_as=\"vector_similarity\",\n        yield_combined_score_as=\"hybrid_score\",\n    )\n\n    results = index.query(filtered_hybrid_query)\n    result_print(results)\n\nelse:\n    print(\"Hybrid search is not available in this version of Redis/redis-py.\")\n```\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003etext_score\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003cth\u003ecategory\u003c/th\u003e\u003cth\u003eprice\u003c/th\u003e\u003cth\u003evector_similarity\u003c/th\u003e\u003cth\u003ehybrid_score\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e3.30321812336\u003c/td\u003e\u003ctd\u003eprod_3\u003c/td\u003e\u003ctd\u003eprofessional tennis racket for competitive players\u003c/td\u003e\u003ctd\u003eequipment\u003c/td\u003e\u003ctd\u003e199.99\u003c/td\u003e\u003ctd\u003e1.0000000596\u003c/td\u003e\u003ctd\u003e1.69096547873\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e3.30321812336\u003c/td\u003e\u003ctd\u003eprod_3\u003c/td\u003e\u003ctd\u003eprofessional tennis racket for competitive players\u003c/td\u003e\u003ctd\u003eequipment\u003c/td\u003e\u003ctd\u003e199.99\u003c/td\u003e\u003ctd\u003e1.0000000596\u003c/td\u003e\u003ctd\u003e1.69096547873\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e0\u003c/td\u003e\u003ctd\u003eprod_2\u003c/td\u003e\u003ctd\u003elightweight running jacket with water resistance\u003c/td\u003e\u003ctd\u003eouterwear\u003c/td\u003e\u003ctd\u003e129.99\u003c/td\u003e\u003ctd\u003e0.794171273708\u003c/td\u003e\u003ctd\u003e0.555919891596\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e0\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e139.99\u003c/td\u003e\u003ctd\u003e0.794171273708\u003c/td\u003e\u003ctd\u003e0.555919891596\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e0\u003c/td\u003e\u003ctd\u003eprod_2\u003c/td\u003e\u003ctd\u003elightweight running jacket with water resistance\u003c/td\u003e\u003ctd\u003eouterwear\u003c/td\u003e\u003ctd\u003e129.99\u003c/td\u003e\u003ctd\u003e0.794171273708\u003c/td\u003e\u003ctd\u003e0.555919891596\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n\n```python\n# Hybrid search with a price filter\nfiltered_hybrid_query = AggregateHybridQuery(\n    text=\"professional equipment\",\n    text_field_name=\"brief_description\",\n    vector=[0.9, 0.1, 0.05],\n    vector_field_name=\"text_embedding\",\n    filter_expression=Num(\"price\") \u003e 100,\n    return_fields=[\"product_id\", \"brief_description\", \"category\", \"price\"],\n    num_results=5\n)\n\nresults = index.query(filtered_hybrid_query)\nresult_print(results)\n```\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003evector_distance\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003cth\u003ecategory\u003c/th\u003e\u003cth\u003eprice\u003c/th\u003e\u003cth\u003evector_similarity\u003c/th\u003e\u003cth\u003etext_score\u003c/th\u003e\u003cth\u003ehybrid_score\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e-1.19209289551e-07\u003c/td\u003e\u003ctd\u003eprod_3\u003c/td\u003e\u003ctd\u003eprofessional tennis racket for competitive players\u003c/td\u003e\u003ctd\u003eequipment\u003c/td\u003e\u003ctd\u003e199.99\u003c/td\u003e\u003ctd\u003e1.0000000596\u003c/td\u003e\u003ctd\u003e3.30321812336\u003c/td\u003e\u003ctd\u003e1.69096547873\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e-1.19209289551e-07\u003c/td\u003e\u003ctd\u003eprod_3\u003c/td\u003e\u003ctd\u003eprofessional tennis racket for competitive players\u003c/td\u003e\u003ctd\u003eequipment\u003c/td\u003e\u003ctd\u003e199.99\u003c/td\u003e\u003ctd\u003e1.0000000596\u003c/td\u003e\u003ctd\u003e3.30321812336\u003c/td\u003e\u003ctd\u003e1.69096547873\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e0.411657452583\u003c/td\u003e\u003ctd\u003eprod_2\u003c/td\u003e\u003ctd\u003elightweight running jacket with water resistance\u003c/td\u003e\u003ctd\u003eouterwear\u003c/td\u003e\u003ctd\u003e129.99\u003c/td\u003e\u003ctd\u003e0.794171273708\u003c/td\u003e\u003ctd\u003e0\u003c/td\u003e\u003ctd\u003e0.555919891596\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e0.411657452583\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e139.99\u003c/td\u003e\u003ctd\u003e0.794171273708\u003c/td\u003e\u003ctd\u003e0\u003c/td\u003e\u003ctd\u003e0.555919891596\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e0.411657452583\u003c/td\u003e\u003ctd\u003eprod_2\u003c/td\u003e\u003ctd\u003elightweight running jacket with water resistance\u003c/td\u003e\u003ctd\u003eouterwear\u003c/td\u003e\u003ctd\u003e129.99\u003c/td\u003e\u003ctd\u003e0.794171273708\u003c/td\u003e\u003ctd\u003e0\u003c/td\u003e\u003ctd\u003e0.555919891596\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n### Using Different Text Scorers\n\nHybrid queries support the same text scoring algorithms as TextQuery:\n\n\n```python\nif HYBRID_SEARCH_AVAILABLE:\n    # Aggregate Hybrid query with TFIDF scorer\n    hybrid_tfidf = HybridQuery(\n        text=\"shoes support\",\n        text_field_name=\"brief_description\",\n        vector=[0.12, 0.18, 0.12],\n        vector_field_name=\"text_embedding\",\n        text_scorer=\"TFIDF\",\n        return_fields=[\"product_id\", \"brief_description\"],\n        num_results=3,\n        combination_method=\"LINEAR\",\n        yield_text_score_as=\"text_score\",\n        yield_vsim_score_as=\"vector_similarity\",\n        yield_combined_score_as=\"hybrid_score\",\n    )\n\n    results = index.query(hybrid_tfidf)\n    result_print(results)\n\nelse:\n    print(\"Hybrid search is not available in this version of Redis/redis-py.\")\n```\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003etext_score\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003cth\u003evector_similarity\u003c/th\u003e\u003cth\u003ehybrid_score\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.66666666667\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003e0.995073735714\u003c/td\u003e\u003ctd\u003e1.496551615\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.66666666667\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003e0.995073735714\u003c/td\u003e\u003ctd\u003e1.496551615\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e1.33333333333\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003ctd\u003e1\u003c/td\u003e\u003ctd\u003e1.1\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n\n```python\n# Aggregate Hybrid query with TFIDF scorer\nhybrid_tfidf = AggregateHybridQuery(\n    text=\"shoes support\",\n    text_field_name=\"brief_description\",\n    vector=[0.12, 0.18, 0.12],\n    vector_field_name=\"text_embedding\",\n    text_scorer=\"TFIDF\",\n    return_fields=[\"product_id\", \"brief_description\"],\n    num_results=3\n)\n\nresults = index.query(hybrid_tfidf)\nresult_print(results)\n```\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003evector_distance\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003cth\u003evector_similarity\u003c/th\u003e\u003cth\u003etext_score\u003c/th\u003e\u003cth\u003ehybrid_score\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e0\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003ctd\u003e1\u003c/td\u003e\u003ctd\u003e4\u003c/td\u003e\u003ctd\u003e1.9\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e0\u003c/td\u003e\u003ctd\u003eprod_2\u003c/td\u003e\u003ctd\u003elightweight running jacket with water resistance\u003c/td\u003e\u003ctd\u003e1\u003c/td\u003e\u003ctd\u003e0\u003c/td\u003e\u003ctd\u003e0.7\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e0\u003c/td\u003e\u003ctd\u003eprod_2\u003c/td\u003e\u003ctd\u003elightweight running jacket with water resistance\u003c/td\u003e\u003ctd\u003e1\u003c/td\u003e\u003ctd\u003e0\u003c/td\u003e\u003ctd\u003e0.7\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n### Runtime Parameters for Vector Search Tuning\n\n**Important:** `AggregateHybridQuery` uses FT.AGGREGATE commands which do NOT support runtime parameters.\n\nRuntime parameters (such as `ef_runtime` for HNSW indexes or `search_window_size` for SVS-VAMANA indexes) are only supported with FT.SEARCH (and partially FT.HYBRID) commands.\n\n**For runtime parameter support, use `HybridQuery`, `VectorQuery`, or `VectorRangeQuery` instead:**\n\n- `HybridQuery`: Supports `ef_runtime` for HNSW indexes\n- `VectorQuery`: Supports all runtime parameters (HNSW and SVS-VAMANA)\n- `VectorRangeQuery`: Supports all runtime parameters (HNSW and SVS-VAMANA)\n- `AggregateHybridQuery`: Does NOT support runtime parameters (uses FT.AGGREGATE)\n\nSee the **Runtime Parameters** section earlier in this notebook for examples of using runtime parameters with `VectorQuery`.\n\n## 3. MultiVectorQuery: Multi-Vector Search\n\nThe `MultiVectorQuery` allows you to search over multiple vector fields simultaneously. This is useful when you have different types of embeddings (e.g., text and image embeddings) and want to find results that match across multiple modalities.\n\nThe final score is calculated as a weighted combination:\n\n```\ncombined_score = w_1 * score_1 + w_2 * score_2 + w_3 * score_3 + ...\n```\n\n### Basic Multi-Vector Query\n\nFirst, we need to import the `Vector` class to define our query vectors:\n\n\n```python\nfrom redisvl.query import MultiVectorQuery, Vector\n\n# Define multiple vectors for the query\ntext_vector = Vector(\n    vector=[0.1, 0.2, 0.1],\n    field_name=\"text_embedding\",\n    dtype=\"float32\",\n    weight=0.7  # 70% weight for text embedding\n)\n\nimage_vector = Vector(\n    vector=[0.8, 0.1],\n    field_name=\"image_embedding\",\n    dtype=\"float32\",\n    weight=0.3  # 30% weight for image embedding\n)\n\n# Create a multi-vector query\nmulti_vector_query = MultiVectorQuery(\n    vectors=[text_vector, image_vector],\n    return_fields=[\"product_id\", \"brief_description\", \"category\"],\n    num_results=5\n)\n\nresults = index.query(multi_vector_query)\nresult_print(results)\n```\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003edistance_0\u003c/th\u003e\u003cth\u003edistance_1\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003cth\u003ecategory\u003c/th\u003e\u003cth\u003escore_0\u003c/th\u003e\u003cth\u003escore_1\u003c/th\u003e\u003cth\u003ecombined_score\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e5.96046447754e-08\u003c/td\u003e\u003ctd\u003e5.96046447754e-08\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e5.96046447754e-08\u003c/td\u003e\u003ctd\u003e5.96046447754e-08\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e0.00985252857208\u003c/td\u003e\u003ctd\u003e0.00266629457474\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e0.995073735714\u003c/td\u003e\u003ctd\u003e0.998666852713\u003c/td\u003e\u003ctd\u003e0.996151670814\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e0.00985252857208\u003c/td\u003e\u003ctd\u003e0.00266629457474\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e0.995073735714\u003c/td\u003e\u003ctd\u003e0.998666852713\u003c/td\u003e\u003ctd\u003e0.996151670814\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e0.00985252857208\u003c/td\u003e\u003ctd\u003e0.0118260979652\u003c/td\u003e\u003ctd\u003eprod_2\u003c/td\u003e\u003ctd\u003elightweight running jacket with water resistance\u003c/td\u003e\u003ctd\u003eouterwear\u003c/td\u003e\u003ctd\u003e0.995073735714\u003c/td\u003e\u003ctd\u003e0.994086951017\u003c/td\u003e\u003ctd\u003e0.994777700305\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n### Adjusting Vector Weights\n\nYou can adjust the weights to prioritize different vector fields:\n\n\n```python\n# More emphasis on image similarity\ntext_vec = Vector(\n    vector=[0.9, 0.1, 0.05],\n    field_name=\"text_embedding\",\n    dtype=\"float32\",\n    weight=0.2  # 20% weight\n)\n\nimage_vec = Vector(\n    vector=[0.1, 0.9],\n    field_name=\"image_embedding\",\n    dtype=\"float32\",\n    weight=0.8  # 80% weight\n)\n\nimage_heavy_query = MultiVectorQuery(\n    vectors=[text_vec, image_vec],\n    return_fields=[\"product_id\", \"brief_description\", \"category\"],\n    num_results=3\n)\n\nprint(\"Results with emphasis on image similarity:\")\nresults = index.query(image_heavy_query)\nresult_print(results)\n```\n\n    Results with emphasis on image similarity:\n\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003edistance_0\u003c/th\u003e\u003cth\u003edistance_1\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003cth\u003ecategory\u003c/th\u003e\u003cth\u003escore_0\u003c/th\u003e\u003cth\u003escore_1\u003c/th\u003e\u003cth\u003ecombined_score\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e-1.19209289551e-07\u003c/td\u003e\u003ctd\u003e0\u003c/td\u003e\u003ctd\u003eprod_3\u003c/td\u003e\u003ctd\u003eprofessional tennis racket for competitive players\u003c/td\u003e\u003ctd\u003eequipment\u003c/td\u003e\u003ctd\u003e1.0000000596\u003c/td\u003e\u003ctd\u003e1\u003c/td\u003e\u003ctd\u003e1.00000001192\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e-1.19209289551e-07\u003c/td\u003e\u003ctd\u003e0\u003c/td\u003e\u003ctd\u003eprod_3\u003c/td\u003e\u003ctd\u003eprofessional tennis racket for competitive players\u003c/td\u003e\u003ctd\u003eequipment\u003c/td\u003e\u003ctd\u003e1.0000000596\u003c/td\u003e\u003ctd\u003e1\u003c/td\u003e\u003ctd\u003e1.00000001192\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e0.14539372921\u003c/td\u003e\u003ctd\u003e0.00900757312775\u003c/td\u003e\u003ctd\u003eprod_6\u003c/td\u003e\u003ctd\u003eswimming goggles with anti-fog coating\u003c/td\u003e\u003ctd\u003eaccessories\u003c/td\u003e\u003ctd\u003e0.927303135395\u003c/td\u003e\u003ctd\u003e0.995496213436\u003c/td\u003e\u003ctd\u003e0.981857597828\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n### Multi-Vector Query with Filters\n\nCombine multi-vector search with filters to narrow results:\n\n\n```python\n# Multi-vector search with category filter\ntext_vec = Vector(\n    vector=[0.1, 0.2, 0.1],\n    field_name=\"text_embedding\",\n    dtype=\"float32\",\n    weight=0.6\n)\n\nimage_vec = Vector(\n    vector=[0.8, 0.1],\n    field_name=\"image_embedding\",\n    dtype=\"float32\",\n    weight=0.4\n)\n\nfiltered_multi_query = MultiVectorQuery(\n    vectors=[text_vec, image_vec],\n    filter_expression=Tag(\"category\") == \"footwear\",\n    return_fields=[\"product_id\", \"brief_description\", \"category\", \"price\"],\n    num_results=5\n)\n\nresults = index.query(filtered_multi_query)\nresult_print(results)\n```\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003edistance_0\u003c/th\u003e\u003cth\u003edistance_1\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003cth\u003ecategory\u003c/th\u003e\u003cth\u003eprice\u003c/th\u003e\u003cth\u003escore_0\u003c/th\u003e\u003cth\u003escore_1\u003c/th\u003e\u003cth\u003ecombined_score\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e5.96046447754e-08\u003c/td\u003e\u003ctd\u003e5.96046447754e-08\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e89.99\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e5.96046447754e-08\u003c/td\u003e\u003ctd\u003e5.96046447754e-08\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e89.99\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e0.00985252857208\u003c/td\u003e\u003ctd\u003e0.00266629457474\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e139.99\u003c/td\u003e\u003ctd\u003e0.995073735714\u003c/td\u003e\u003ctd\u003e0.998666852713\u003c/td\u003e\u003ctd\u003e0.996510982513\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e0.00985252857208\u003c/td\u003e\u003ctd\u003e0.00266629457474\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003ctd\u003efootwear\u003c/td\u003e\u003ctd\u003e139.99\u003c/td\u003e\u003ctd\u003e0.995073735714\u003c/td\u003e\u003ctd\u003e0.998666852713\u003c/td\u003e\u003ctd\u003e0.996510982513\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n## Comparing Query Types\n\nLet's compare the three query types side by side:\n\n\n```python\n# TextQuery - keyword-based search\ntext_q = TextQuery(\n    text=\"shoes\",\n    text_field_name=\"brief_description\",\n    return_fields=[\"product_id\", \"brief_description\"],\n    num_results=3\n)\n\nprint(\"TextQuery Results (keyword-based):\")\nresult_print(index.query(text_q))\nprint()\n```\n\n    TextQuery Results (keyword-based):\n\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003escore\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.9647332596813154\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.9647332596813154\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.148612199701887\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n    \n\n\n\n```python\nif HYBRID_SEARCH_AVAILABLE:\n    # HybridQuery - combines text and vector search\n    hybrid_q = HybridQuery(\n        text=\"shoes\",\n        text_field_name=\"brief_description\",\n        vector=[0.1, 0.2, 0.1],\n        vector_field_name=\"text_embedding\",\n        return_fields=[\"product_id\", \"brief_description\"],\n        num_results=3,\n        combination_method=\"LINEAR\",\n        yield_text_score_as=\"text_score\",\n        yield_vsim_score_as=\"vector_similarity\",\n        yield_combined_score_as=\"hybrid_score\",\n    )\n\n    results = index.query(hybrid_q)\n\nelse:\n    hybrid_q = AggregateHybridQuery(\n        text=\"shoes\",\n        text_field_name=\"brief_description\",\n        vector=[0.1, 0.2, 0.1],\n        vector_field_name=\"text_embedding\",\n        return_fields=[\"product_id\", \"brief_description\"],\n        num_results=3,\n    )\n\n    results = index.query(hybrid_q)\n\n\nprint(f\"{hybrid_q.__class__.__name__} Results (text + vector):\")\nresult_print(results)\nprint()\n```\n\n    HybridQuery Results (text + vector):\n\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003etext_score\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003cth\u003evector_similarity\u003c/th\u003e\u003cth\u003ehybrid_score\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.96473325968\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003ctd\u003e1.58941995704\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.96473325968\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003ctd\u003e1.58941995704\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e2.1486121997\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003ctd\u003e0.995073735714\u003c/td\u003e\u003ctd\u003e1.34113527491\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n    \n\n\n\n```python\n# MultiVectorQuery - searches multiple vector fields\nmv_text = Vector(\n    vector=[0.1, 0.2, 0.1],\n    field_name=\"text_embedding\",\n    dtype=\"float32\",\n    weight=0.5\n)\n\nmv_image = Vector(\n    vector=[0.8, 0.1],\n    field_name=\"image_embedding\",\n    dtype=\"float32\",\n    weight=0.5\n)\n\nmulti_q = MultiVectorQuery(\n    vectors=[mv_text, mv_image],\n    return_fields=[\"product_id\", \"brief_description\"],\n    num_results=3\n)\n\nprint(\"MultiVectorQuery Results (multiple vectors):\")\nresult_print(index.query(multi_q))\n```\n\n    MultiVectorQuery Results (multiple vectors):\n\n\n\n\u003ctable\u003e\u003ctr\u003e\u003cth\u003edistance_0\u003c/th\u003e\u003cth\u003edistance_1\u003c/th\u003e\u003cth\u003eproduct_id\u003c/th\u003e\u003cth\u003ebrief_description\u003c/th\u003e\u003cth\u003escore_0\u003c/th\u003e\u003cth\u003escore_1\u003c/th\u003e\u003cth\u003ecombined_score\u003c/th\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e5.96046447754e-08\u003c/td\u003e\u003ctd\u003e5.96046447754e-08\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e5.96046447754e-08\u003c/td\u003e\u003ctd\u003e5.96046447754e-08\u003c/td\u003e\u003ctd\u003eprod_1\u003c/td\u003e\u003ctd\u003ecomfortable running shoes for athletes\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003ctd\u003e0.999999970198\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e0.00985252857208\u003c/td\u003e\u003ctd\u003e0.00266629457474\u003c/td\u003e\u003ctd\u003eprod_5\u003c/td\u003e\u003ctd\u003ebasketball shoes with excellent ankle support\u003c/td\u003e\u003ctd\u003e0.995073735714\u003c/td\u003e\u003ctd\u003e0.998666852713\u003c/td\u003e\u003ctd\u003e0.996870294213\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n\n## Best Practices\n\n### When to Use Each Query Type:\n\n1. **`TextQuery`**:\n   - When you need precise keyword matching\n   - For traditional search engine functionality\n   - When text relevance scoring is important\n   - Example: Product search, document retrieval\n\n2. **`HybridQuery`**:\n   - When you want to combine keyword and semantic search\n   - For improved search quality over pure text or vector search\n   - When you have both text and vector representations of your data\n   - Example: E-commerce search, content recommendation\n\n3. **`MultiVectorQuery`**:\n   - When you have multiple types of embeddings (text, image, audio, etc.)\n   - For multi-modal search applications\n   - When you want to balance multiple semantic signals\n   - Example: Image-text search, cross-modal retrieval\n\n\n```python\n# Cleanup\nindex.delete()\n```\n",
  "tags": [],
  "last_updated": "2026-04-21T14:39:33+02:00"
}
