【高速缓存】RedisVL 高级查询(全文搜索、混合搜索和 多向量搜索)

【高速缓存】RedisVL 高级查询(全文搜索、混合搜索和 多向量搜索)

RedisVL 不仅支持基本的向量相似性搜索,还提供了多种高级查询类型,帮助您构建更智能、更精准的检索应用。本指南将深入讲解三种核心高级查询——TextQuery(全文搜索)、HybridQuery(混合搜索)和MultiVectorQuery(多向量搜索)。


📌 前提条件

在开始之前,请确保您已具备以下环境:

  • 安装 RedisVL:pip install redisvl
  • 一个运行中的 Redis 实例(推荐 Redis 8+ 或 Redis Cloud)
  • 如需使用HybridQuery,需要 Redis >= 8.4.0 且redis-py >= 7.1.0

🎯 该要

  • 使用TextQuery进行全文搜索,并灵活调整评分算法
  • 利用HybridQueryAggregateHybridQuery将文本搜索与向量搜索相结合,获得“语义 + 关键词”的双重优势
  • 通过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,categoryTag精确过滤
brief_description,full_descriptionText全文搜索
price,ratingNumeric数值范围过滤
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_descriptionfull_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

是否有多个向量字段?

MultiVectorQuery

HybridQuery

是否有多个向量字段?

纯向量搜索(VectorQuery,不在本指南)


🧠 最佳实践

  • TextQuery 适用场景:当查询词明确、需要精确匹配时(如产品型号、专有名词)。若数据量不大且实时性要求高,文本搜索性能优越。
  • HybridQuery 推荐:对于电商、内容推荐等混合场景,混合搜索能同时捕获用户意图(向量)和关键词(文本),效果更好。建议先用默认 alpha(0.3)测试,再根据业务调整。
  • MultiVectorQuery 多模态利器:如果您的数据有图像、音频等多种向量,多向量查询可以让您统一打分排序,避免分别检索再合并的繁琐。
  • 停用词策略:如果您的数据包含常见的停用词且这些词具有业务含义(如公司名称中的 “of”),请在索引级别禁用停用词;如果只是查询时想忽略某些词,使用查询级停用词更灵活。
  • 版本兼容:生产环境务必检查 Redis 和 redis-py 版本,以决定使用HybridQuery还是AggregateHybridQuery。建议升级到 Redis 8.4+ 以享受完整功能。

🧹 清理资源

示例结束后,可以删除测试索引以释放资源:

index.delete(drop=True)