混合搜索在一个查询中结合了全文(BM25)搜索与KNN向量搜索,使用倒数排名融合(RRF)融合结果。这利用了两种检索方法的优势:BM25的关键词精确性与向量相似度的语义理解。
全文搜索擅长精确关键词匹配和稀有术语,但会遗漏概念上相似的内容。向量搜索捕捉语义含义,但在模糊查询中可能产生噪声。混合搜索结合两者,因此在任一或两者信号中得分高的文档会被展示。
RRF是一种基于排名的融合算法。它基于排名位置而非原始分数进行操作,避免了需要归一化不兼容的分数尺度(BM25分数是无界的;KNN距离有不同的尺度)。
RRF_score(d) = SUM over all result sets r: weight_r / (rank_constant + rank_r(d))
其中:
d是一个文档rank_r(d)是文档在结果集r中的1-based位置(按该检索器的分数排序)rank_constant是一个平滑常数(默认:60,可通过rank_constant选项配置)weight_r是每个检索器的可选权重(默认:1.0)
如果文档未出现在特定结果集中,该集合对该文档的贡献为0。
rank_constant=60是默认值。- 较低的值(例如10)会放大排名靠前项目的差异。
- 较高的值(例如100)会使排名间的影响力更均匀分布。
在 WHERE 子句中结合 MATCH(...) 和 KNN(...),并使用 OPTION fusion_method='rrf':
- SQL
- JSON
SELECT id, hybrid_score()
FROM t
WHERE match('machine learning')
AND knn(vec, (0.1, 0.1, 0.1, 0.1))
OPTION fusion_method='rrf';这会将文本搜索和 KNN 搜索作为独立的并行子查询运行,然后使用 RRF 融合结果。如果没有 fusion_method='rrf',查询会作为常规 KNN 搜索运行,仅通过文本匹配进行过滤(预混合行为)。
hybrid_score()- RRF 融合分数(仅在混合查询中可用)weight()- BM25 文本匹配分数knn_dist()- 向量距离(如果有多个 KNN 子查询,则取最小值)
| 选项 | 类型 | 默认值 | 描述 |
|---|---|---|---|
fusion_method |
字符串 | (无) | 设置为 'rrf' 以启用混合搜索。必需。 |
rank_constant |
整数 | 60 | RRF 公式中的平滑常数 |
window_size |
整数 | 0(自动) | 每个子查询在融合前检索的结果数量。当为0时,从 KNN k(带过采样)和查询 LIMIT 自动计算 |
fusion_weights |
元组 | (全部为1.0) | RRF 评分中每个子查询的权重 |
- SQL
- JSON
-- Default rank_constant=60 (gentler ranking)
SELECT id, hybrid_score() FROM t
WHERE match('machine learning') AND knn(vec, (0.1, 0.1, 0.1, 0.1))
OPTION fusion_method='rrf';
-- rank_constant=10 (sharper top-rank differences)
SELECT id, hybrid_score() FROM t
WHERE match('machine learning') AND knn(vec, (0.1, 0.1, 0.1, 0.1))
OPTION fusion_method='rrf', rank_constant=10;标准 WHERE 过滤器可与混合搜索一起使用。过滤器应用于文本和 KNN 子查询:
- SQL
- JSON
SELECT id, category, hybrid_score()
FROM t
WHERE match('machine learning')
AND knn(vec, (0.1, 0.1, 0.1, 0.1))
AND category = 1
OPTION fusion_method='rrf';默认情况下,结果按 hybrid_score() DESC 排序。您可以覆盖此设置:
- SQL
-- Sort by hybrid score ascending
SELECT id, hybrid_score() FROM t
WHERE match('machine learning') AND knn(vec, (0.1, 0.1, 0.1, 0.1))
ORDER BY hybrid_score() ASC
OPTION fusion_method='rrf';
-- Sort by text weight
SELECT id, weight() FROM t
WHERE match('machine learning') AND knn(vec, (0.1, 0.1, 0.1, 0.1))
ORDER BY weight() DESC, id ASC
OPTION fusion_method='rrf';
-- Sort by KNN distance
SELECT id, knn_dist() FROM t
WHERE match('machine learning') AND knn(vec, (0.1, 0.1, 0.1, 0.1))
ORDER BY knn_dist() ASC
OPTION fusion_method='rrf';如果文本查询未匹配任何文档,仅 KNN 结果会对 RRF 分数做出贡献:
SELECT id, hybrid_score() FROM t
WHERE match('xyznonexistent') AND knn(vec, (0.1, 0.1, 0.1, 0.1))
OPTION fusion_method='rrf';
-- Returns results ranked purely by KNN rank
单个混合查询可以将文本搜索与不同向量属性上的多个 KNN 搜索结合。所有内容通过 RRF 融合:
- SQL
- JSON
-- Three-way fusion: text + vec1 KNN + vec2 KNN
SELECT id, hybrid_score()
FROM t
WHERE match('machine learning')
AND knn(vec1, (0.1, 0.1, 0.1, 0.1))
AND knn(vec2, (1.0, 0.0, 0.0, 0.0))
OPTION fusion_method='rrf';
-- KNN-only fusion (no text), two vector searches
SELECT id, hybrid_score()
FROM t
WHERE knn(vec1, (0.1, 0.1, 0.1, 0.1))
AND knn(vec2, (1.0, 0.0, 0.0, 0.0))
OPTION fusion_method='rrf';没有 fusion_method 的多个 KNN 搜索会产生错误。
默认情况下,所有子查询贡献相等(权重1.0)。要为文本与 KNN 搜索赋予不同的重要性,请使用 fusion_weights 并使用显式别名:
- SQL
- JSON
SELECT id, hybrid_score()
FROM t
WHERE match('machine learning') AS text
AND knn(vec1, (0.1, 0.1, 0.1, 0.1)) AS dense1
AND knn(vec2, (1.0, 0.0, 0.0, 0.0)) AS dense2
OPTION fusion_method='rrf',
fusion_weights=(text=0.7, dense1=0.2, dense2=0.1);SQL:
- 使用
AS alias对MATCH(...)和KNN(...)命名。没有隐式/默认别名。 - 省略的别名默认权重为1.0。
- 引用不存在的别名会产生错误。
JSON:
"query"是全文子查询的固定别名。- 每个 KNN 条目通过
"name"属性设置 KNN 别名。 - 命名为
"query"的 KNN 条目与文本别名冲突并产生错误。 fusion_weights中不支持隐式别名(无显式"name"的字段名)。
您可以仅为部分子查询指定权重;其余默认为1.0:
-- Only boost text, KNN searches default to weight 1.0
SELECT id, hybrid_score()
FROM t
WHERE match('machine learning') AS text
AND knn(vec1, (0.1, 0.1, 0.1, 0.1)) AS dense1
AND knn(vec2, (1.0, 0.0, 0.0, 0.0)) AS dense2
OPTION fusion_method='rrf', fusion_weights=(text=2.0);
对于在 float_vector 属性上配置了自动嵌入的表,hybrid_match() 提供了一个简写,可自动从单个查询字符串运行文本和 KNN 搜索:
- SQL
-- Explicit vector field
SELECT id, hybrid_score() FROM t WHERE hybrid_match('machine learning', vec);
-- Auto-detect vector field (requires exactly one auto-embedding attribute)
SELECT id, hybrid_score() FROM t WHERE hybrid_match('machine learning');
-- With custom k and rank_constant
SELECT id, hybrid_score() FROM t
WHERE hybrid_match('machine learning', vec, {k=3})
OPTION rank_constant=10;
-- With attribute filter
SELECT id, hybrid_score() FROM t
WHERE hybrid_match('machine learning', vec) AND category=1;hybrid_match() 自动执行以下操作:
- 将文本查询作为 BM25 全文搜索运行
- 从同一文本字符串生成嵌入
- 使用该嵌入运行 KNN 搜索
- 通过 RRF 融合结果
要求:向量属性必须为自动嵌入配置model_name和from。如果没有配置,hybrid_match()将返回错误。
对于具有自动嵌入的表,JSON中可以使用"hybrid"属性作为简写:
- JSON
POST /search
{
"table": "hj",
"hybrid": { "query": "machine learning" }
}
POST /search
{
"table": "hj",
"hybrid": { "query": "machine learning", "field": "vec" }
}
POST /search
{
"table": "hj",
"hybrid": { "query": "machine learning" },
"options": { "rank_constant": 10 }
}"hybrid"属性不能与"knn"一起使用。
当向量属性具有自动嵌入时,可以在knn对象中使用"query"(字符串)代替"query_vector"(数组):
POST /search
{
"table": "ht",
"knn": { "field": "vec", "query": "machine learning", "k": 5 },
"query": { "match": { "title": "machine learning" } },
"options": { "fusion_method": "rrf" }
}
字符串会在查询时自动嵌入。如果没有配置自动嵌入,这将返回错误。
内部地,混合查询会被拆分为N+1个并行子查询:
- 任务0:全文(BM25)子查询(如果文本查询为空则跳过,以避免用全扫描结果污染RRF)
- 任务1..N:每个
knn(...)条目对应一个KNN子查询
所有子查询并发运行。在全部完成之后,RRF融合:
- 从每个子查询收集排序结果
- 对于每个文档,累积其出现在每个子查询中的RRF得分贡献
- 按融合后的RRF得分降序排序
- 将
knn_dist()设置为每个文档在所有KNN子查询中的最小距离 - 保留来自文本子查询的
weight()