RedisVL 不仅支持基本的向量相似性搜索,还提供了多种高级查询类型,帮助您构建更智能、更精准的检索应用。本指南将深入讲解三种核心高级查询——TextQuery(全文搜索)、HybridQuery(混合搜索)和MultiVectorQuery(多向量搜索)。
📌 前提条件
在开始之前,请确保您已具备以下环境:
- 安装 RedisVL:
pip install redisvl - 一个运行中的 Redis 实例(推荐 Redis 8+ 或 Redis Cloud)
- 如需使用
HybridQuery,需要 Redis >= 8.4.0 且redis-py >= 7.1.0
🎯 该要
- 使用
TextQuery进行全文搜索,并灵活调整评分算法 - 利用
HybridQuery和AggregateHybridQuery将文本搜索与向量搜索相结合,获得“语义 + 关键词”的双重优势 - 通过
MultiVectorQuery跨多个向量字段(如文本向量、图像向量)进行联合检索 - 配置索引级或查询级停用词,优化文本搜索效果
📦 数据准备与索引定义
首先准备一组商品数据,包含文本描述、类别、价格、评分以及两种向量(文本嵌入和图像嵌入)。这些数据将贯穿全文示例。
importnumpyasnpfromjupyterutilsimportresult_print data=[{'product_id':'prod_1','brief_description':'comfortable running shoes for athletes','full_description':'Engineered with a dual-layer EVA foam midsole...','category':'footwear','price':89.99,'rating':4.5,'text_embedding':np.array([0.1,0.2,0.1],dtype=np.float32).tobytes(),'image_embedding':np.array([0.8,0.1],dtype=np.float32).tobytes(),},# ... 更多商品(省略具体内容,与原文一致)]定义索引模式(Schema)
索引模式决定了 Redis 如何存储和索引字段。本例中我们定义了:
| 字段名 | 类型 | 用途 |
|---|---|---|
product_id,category | Tag | 精确过滤 |
brief_description,full_description | Text | 全文搜索 |
price,rating | Numeric | 数值范围过滤 |
text_embedding(3维) | Vector | 文本语义向量 |
image_embedding(2维) | Vector | 图像语义向量 |
schema={"index":{"name":"advanced_queries","prefix":"products","storage_type":"hash",},"fields":[{"name":"product_id","type":"tag"},{"name":"category","type":"tag"},{"name":"brief_description","type":"text"},{"name":"full_description","type":"text"},{"name":"price","type":"numeric"},{"name":"rating","type":"numeric"},{"name":"text_embedding","type":"vector","attrs":{"dims":3,"distance_metric":"cosine","algorithm":"flat","datatype":"float32"}},{"name":"image_embedding","type":"vector","attrs":{"dims":2,"distance_metric":"cosine","algorithm":"flat","datatype":"float32"}}],}创建索引并加载数据:
fromredisvl.indeximportSearchIndex index=SearchIndex.from_dict(schema,redis_url="redis://localhost:6379")index.create(overwrite=True)keys=index.load(data)print(f"已加载{len(keys)}个产品")1️⃣ TextQuery:全文搜索
TextQuery是面向关键词的搜索工具,支持多种相关性评分算法(BM25、TF‑IDF),并可结合过滤器、多字段权重及停用词优化。
基本原理
全文搜索的核心是倒排索引。Redis 将文本字段分词后构建索引,查询时根据词项匹配情况计算文档与查询的相关性分数。评分算法直接影响排序效果:
- BM25(BM25STD):一种基于概率检索模型的成熟算法,考虑词频、文档长度等因素,通常比 TF‑IDF 更精准。
- TF‑IDF:经典算法,计算简单,适合快速原型。
基本用法
fromredisvl.queryimportTextQuery text_query=TextQuery(text="running shoes",text_field_name="brief_description",return_fields=["product_id","brief_description","category","price"],num_results=5)results=index.query(text_query)result_print(results)输出显示匹配到的商品,并按相关性分数降序排列。
评分算法对比
您可以显式指定text_scorer参数:
# BM25 标准评分(默认)bm25_query=TextQuery(...,text_scorer="BM25STD")# TF‑IDF 评分tfidf_query=TextQuery(...,text_scorer="TFIDF")💡建议:对于一般应用,BM25 通常表现更佳;若需快速实现或简单场景,TF‑IDF 也可胜任。
结合过滤器
使用filter_expression可以缩小搜索范围,例如只搜索某类别或价格区间的商品:
fromredisvl.query.filterimportTag,Num# 只查找 footwear 类别中的 "shoes"filtered=TextQuery(text="shoes",text_field_name="brief_description",filter_expression=Tag("category")=="footwear",...)# 价格小于 100price_filtered=TextQuery(text="comfortable",filter_expression=Num("price")<100,...)多字段加权搜索
有时不同字段的重要性不同,例如brief_description比full_description更能代表商品核心信息。您可以给每个字段分配权重:
weighted_query=TextQuery(text="shoes",text_field_name={"brief_description":1.0,"full_description":0.5},...)这样,命中brief_description的文档会比仅命中full_description的获得更高分数。
停用词(Stopwords)详解
停用词是指那些出现频率极高但对语义贡献很小的词(如 “the”, “for”)。Redis 允许在查询级别和索引级别配置停用词,两者作用机制不同:
| 配置层级 | 作用时机 | 影响范围 |
|---|---|---|
查询级(TextQuery.stopwords) | 查询时,客户端过滤查询词 | 仅影响当前查询 |
索引级(Index.stopwords) | 索引创建时,服务器决定哪些词被收录 | 影响整个索引,所有查询 |
查询级停用词示例
# 使用英语默认停用词(过滤 "the", "for" 等)query_english=TextQuery(text="the best shoes for running",stopwords="english",...)# 自定义停用词列表(只过滤 "for", "with")query_custom=TextQuery(text="professional equipment for athletes",stopwords=["for","with"],...)# 完全不禁用停用词(保留所有词)query_none=TextQuery(text="the best shoes for running",stopwords=None,...)索引级停用词
在创建索引时,可通过index.stopwords字段控制哪些词不被索引。默认 Redis 会使用内置停用词列表。若要禁用所有停用词(即索引所有词),可设置为空列表[](即STOPWORDS 0)。这在搜索专有名词(如 “Bank of America”)时非常有用,因为 “of” 不会被过滤掉。
stopwords_schema={"index":{"name":"company_index","stopwords":[]# 禁用所有停用词},"fields":[...]}⚠️注意:索引级停用词在索引创建时生效,且修改后需重建索引。查询级停用词则更灵活,可按需调整。
2️⃣ HybridQuery:混合搜索
混合搜索将全文检索与向量语义检索相结合,既利用关键词精准匹配,又借助向量捕获深层语义,显著提升检索质量。Redis 从 8.4.0 开始原生支持FT.HYBRID命令,RedisVL 提供了HybridQuery类(新)和AggregateHybridQuery(旧)两种实现。
版本说明
- HybridQuery:需要 Redis >= 8.4.0 且 redis-py >= 7.1.0,支持更丰富的功能(如 RRF、运行时参数)。
- AggregateHybridQuery:兼容旧版 Redis,基于
FT.AGGREGATE实现,功能略少(不支持 RRF,且不支持运行时参数)。
以下示例默认使用HybridQuery,若环境不满足则会降级使用AggregateHybridQuery。
混合搜索的工作原理
混合搜索并行执行文本查询和向量查询,分别得到两个分数(文本相关度和向量相似度),然后通过组合方法将二者融合为一个最终得分。下图展示了这一流程:
组合方法
RedisVL 支持两种融合策略:
- 线性组合(LINEAR):
final_score = α * text_score + (1 - α) * vector_score,其中α控制文本与向量的权重。默认α = 0.3(即向量占 70%)。 - 倒数排名融合(RRF):不直接使用分数,而是基于各自排名进行融合,公式为
RRF = Σ 1/(k + rank)。这种方法对排名靠前的文档给予更高权重,能有效缓解分数尺度不一致的问题。
基本用法
fromredisvl.queryimportHybridQuery hybrid_query=HybridQuery(text="running shoes",text_field_name="brief_description",vector=[0.1,0.2,0.1],# 查询向量vector_field_name="text_embedding",return_fields=["product_id","brief_description","category","price"],num_results=5,yield_text_score_as="text_score",yield_vsim_score_as="vector_similarity",combination_method="LINEAR",yield_combined_score_as="hybrid_score",)results=index.query(hybrid_query)输出中会包含文本分数、向量相似度以及融合后的混合分数。
调整 alpha 参数
通过调整linear_alpha(HybridQuery)或alpha(AggregateHybridQuery)可以控制文本和向量的权重:
alpha=1.0:纯文本搜索alpha=0.0:纯向量搜索alpha=0.1:文本占 10%,向量占 90%(向量优先)
# 向量优先查询vector_heavy=HybridQuery(...,linear_alpha=0.1,combination_method="LINEAR")🔄注意:
AggregateHybridQuery中的alpha含义相反——它表示向量权重,所以alpha=0.9表示向量占 90%,文本占 10%。
使用 RRF(仅 HybridQuery)
rrf_query=HybridQuery(...,combination_method="RRF",rrf_window=60,# 可选,默认 60rrf_constant=1,# 可选,默认 1)混合搜索 + 过滤器
与TextQuery类似,您也可以添加过滤条件:
filtered_hybrid=HybridQuery(...,filter_expression=Num("price")>100,)运行时参数(仅 HybridQuery)
对于 HNSW 索引,可以通过ef_runtime参数在查询时动态调整搜索范围,以平衡精度与速度。HybridQuery支持此参数,而AggregateHybridQuery不支持(因为它使用FT.AGGREGATE)。
hybrid_with_runtime=HybridQuery(...,ef_runtime=200,# 针对 HNSW 索引)3️⃣ MultiVectorQuery:多向量搜索
当您的数据包含多种模态的向量(如文本向量、图像向量、音频向量)时,MultiVectorQuery允许您同时对这些向量字段进行检索,并按权重综合排序。
原理
每个查询向量都带有一个权重,最终得分为所有向量相似度的加权和:
combined_score = w1 * sim1 + w2 * sim2 + ... + wn * simn其中wi为第 i 个向量的权重,simi为其与查询向量的相似度(余弦距离转换为相似度,1 - 距离)。
基本用法
fromredisvl.queryimportMultiVectorQuery,Vector# 定义每个向量查询text_vector=Vector(vector=[0.1,0.2,0.1],field_name="text_embedding",dtype="float32",weight=0.7)image_vector=Vector(vector=[0.8,0.1],field_name="image_embedding",dtype="float32",weight=0.3)multi_query=MultiVectorQuery(vectors=[text_vector,image_vector],return_fields=["product_id","brief_description"],num_results=5)results=index.query(multi_query)结果中会显示每个向量的单独得分和组合得分。
调整权重
您可以通过修改weight来突出某个模态的重要性,例如更侧重图像相似性:
text_vec.weight=0.2image_vec.weight=0.8结合过滤器
同样支持过滤:
filtered_multi=MultiVectorQuery(...,filter_expression=Tag("category")=="footwear",)📊 三种查询类型对比
为了让您更直观地选择合适的方法,下表对比了各自特点:
| 查询类型 | 核心能力 | 适用场景 | 关键参数 |
|---|---|---|---|
| TextQuery | 纯关键词全文搜索 | 精准匹配、传统搜索引擎 | 文本评分器、多字段权重、停用词 |
| HybridQuery | 文本 + 向量融合 | 兼顾精确与语义,适用于大多数搜索场景 | 组合方法(LINEAR/RRF)、alpha、运行时参数 |
| MultiVectorQuery | 多模态向量联合检索 | 多模态搜索(图文、音视频等) | 向量权重、多向量组合 |
下图为决策流程图,帮助您快速定位:
🧠 最佳实践
- TextQuery 适用场景:当查询词明确、需要精确匹配时(如产品型号、专有名词)。若数据量不大且实时性要求高,文本搜索性能优越。
- HybridQuery 推荐:对于电商、内容推荐等混合场景,混合搜索能同时捕获用户意图(向量)和关键词(文本),效果更好。建议先用默认 alpha(0.3)测试,再根据业务调整。
- MultiVectorQuery 多模态利器:如果您的数据有图像、音频等多种向量,多向量查询可以让您统一打分排序,避免分别检索再合并的繁琐。
- 停用词策略:如果您的数据包含常见的停用词且这些词具有业务含义(如公司名称中的 “of”),请在索引级别禁用停用词;如果只是查询时想忽略某些词,使用查询级停用词更灵活。
- 版本兼容:生产环境务必检查 Redis 和 redis-py 版本,以决定使用
HybridQuery还是AggregateHybridQuery。建议升级到 Redis 8.4+ 以享受完整功能。
🧹 清理资源
示例结束后,可以删除测试索引以释放资源:
index.delete(drop=True)