OpenSearch/Ingest Pipeline + k-NN 在 ABP 的“双索引”落地
OpenSearch/Ingest Pipeline + k-NN 在 ABP 的“双索引”落地 🧭
📚 目录
- OpenSearch/Ingest Pipeline + k-NN 在 ABP 的“双索引”落地 🧭
-
- 0) 摘要(TL;DR)🧾
- 1) 架构总览 🗺️
- 2) 目标与差异化 🎯
- 3) 版本矩阵与降级策略 🧱
- 4) 索引模板与映射 🧩
-
- 4.1 文档索引(Lucene HNSW + 余弦)
- 4.2 日志索引(吞吐优先)
- 5) Ingest Pipeline(写入前置)🛠️
-
- 5.1 文档:清洗 + 嵌入
- 5.2 日志:结构化提取 + 可选摘要向量
- 5.3 写入链路
- 6) Search Pipeline(Normalization / RRF / Explanation)🧪
-
- 6.1 归一化(2.10+)
- 6.2 RRF(2.19+)
- 7) Hybrid 查询(3.0+ Common Filter / 2.x 兼容)🧠
-
- 7.1 OpenSearch 3.0+(推荐)
- 7.2 OpenSearch 2.x(无 Common Filter,用 `bool/filter` 包裹)
- 7.3 Hybrid 检索时序(Normalization vs RRF)
- 8) ABP 实现 🧰
-
- 8.1 客户端注册(LowLevelClient)
- 8.2 DTO 与服务(3.x Common Filter;2.x 分支见注释)
- 9) 多租户映射与安全 🔐
- 10) 运维与可观测 📈
- 11) 成本与容量 💰
- 12) 风险与常见坑 ✅
- 13) DevTools 顺序 🧪
- 14) FAQ ❓
0) 摘要(TL;DR)🧾
-
写入侧(ingest):用
text_embedding
处理器在索引前生成向量并写入knn_vector
;通过index.default_pipeline
持久启用。 -
检索侧(search):用 Hybrid Query 将 BM25 与向量相似度合并;在 Search Pipeline 使用
normalization-processor
(2.10+)进行 L2/MinMax/Z-Score 归一化 + 算术/几何/调和加权;或score-ranker-processor
(2.19+)进行 RRF 融合;
需要调试时打开hybrid_score_explanation
(2.19+)。
-
多租户:
tenantId
贯穿命名/路由/过滤;共享索引叠加 DLS/FLS。 -
参数建议:
size
建议先取 100–200;Lucene HNSW 忽略ef_search
(由查询k
代入),重点调m
与ef_construction
。
1) 架构总览 🗺️
2) 目标与差异化 🎯
- 目标:在 ABP vNext 内落地“文档索引 + 日志索引”双轨方案,端到端可复现、可评测、可扩展。
- 差异化:完全采用 OpenSearch 原生(
knn_vector
、Ingest/Search Pipeline、Hybrid/RRF),避免“ES + 外置向量库 + 网关融合”的一致性/可用性隐患。 - 多租户:以
ICurrentTenant
注入租户上下文到索引命名或查询过滤,结合 OpenSearch 安全(DLS/FLS)实现细粒度隔离。
3) 版本矩阵与降级策略 🧱
能力 | 最低版本 | 说明 |
---|---|---|
Normalization Processor | 2.10 | 归一化与加权(L2/MinMax/Z-Score + 三均值) |
Hybrid Query(官方文档流程) | 2.11 | match + neural/knn 混排 |
RRF(score-ranker-processor) | 2.19 | 分数不可比场景更稳健 |
hybrid 顶层 filter (Common Filter) | 3.0 | 统一过滤,无需在各子句重复 |
k-NN gRPC(GA) | 3.2 | 高并发向量检索可选 |
降级策略:
- 2.x 无 Common Filter → 用外层
bool/filter
或在子句重复过滤; - 无 RRF → 用 Normalization;
- 低版本不支持某处理器 → 临时指定
?search_pipeline=_none
做退避。
4) 索引模板与映射 🧩
模型以
all-MiniLM-L6-v2
(384 维、cosine)为例;换模型请同步调整dimension
/space_type
。
4.1 文档索引(Lucene HNSW + 余弦)
PUT _index_template/docs-template
{"index_patterns": ["*-docs-*"],"template": {"settings": {"index.knn": true,"index.default_pipeline": "docs-embed-v1","index.search.default_pipeline": "hybrid-norm-v1","refresh_interval": "1s"},"mappings": {"properties": {"tenantId": { "type": "keyword" },"title": { "type": "text" },"content": { "type": "text" },"embedding": {"type": "knn_vector","dimension": 384,"method": {"name": "hnsw","engine": "lucene","space_type": "cosinesimil","parameters": { "m": 32, "ef_construction": 128 }}/* 可选降本: "data_type": "byte" 仅 Lucene 支持 */}}}}
}
4.2 日志索引(吞吐优先)
PUT _index_template/logs-template
{"index_patterns": ["*-logs-*"],"template": {"settings": {"index.knn": true,"index.default_pipeline": "logs-enrich-v1","refresh_interval": "30s" /* 高吞吐写入可调大 */},"mappings": {"properties": {"tenantId": { "type": "keyword" },"level": { "type": "keyword" },"ts":