全文检索
- 内部部署仓库 docker-compose.yaml / Helm values.yaml(search/search-producer/search-tools/doc-index/drive-index profile段、deployment/configmap/pvc/kafka-init/ensure job)/ nginx 路由配置(2026-09-21 阶段一解析)
- source-repos/octo-server/docs/messages-search/(search-flow-cheatsheet.md, v1.8-opensearch-mapping.md, octo-server-search-dev.md, indexer-os-changes.md)——开源octo-server搜索模块开发文档
- source-repos/octo-server/modules/messages_search/(源码目录)
- source-repos/octo-server/modules/base/sql/20260614000001_searchetl_init.sql
- OCTO知识库建设组父群 / 2026-09-21 / Octo产品管家回答(Search模块完整事实确认)
- 02-architecture/OCTO全组件服务清单.md(第十一/十二/十三节)
- 00-inbox/product-bot-answers/2026-09-22-P1-round1-Q5-Search全文搜索深度回答.md(Q5源码部分确认+私有仓边界)
- 00-inbox/product-bot-answers/2026-09-22-P1-round2-Q6-Drive网盘深度回答.md(Q6 P0纠偏:octo-search-indexer仅管消息附件,Drive有独立搜索后端)
全文搜索Search模块说明 v0.5
🔴 P0纠偏1(2026-09-22 Q5源码确认):v0.3存在"统一大索引近实时搜索"的过度表述。Q5源码确认:搜索采用两套索引(消息类 vs 文档/网盘类),"分别查再合并"形态,❌统一大索引未找到证据;indexer是独立服务异步消费(秒级到分钟级延迟),非严格实时同步;文件正文通过Apache Tika抽取。权重排序、两索引merge逻辑在私有仓,当前不可见,不做断言。
🔴 P0纠偏2(2026-09-22 Q6源码确认):v0.4误写"文档/网盘走独立octo-search-indexer仓"——Q6源码级确认:开源octo-search-indexer仓(es-indexer镜像`mininglamposs/octo-search-indexer:latest`)仅处理消息附件抽取(Kafka topic `octo.message.v1`, consumer group `file-extractor`, payload.type=8→Tika→OS partial update写`payload.file.content`),不处理Drive文件索引,开源仓无`octo.driveindex.v1` topic消费逻辑。Drive有独立搜索后端(私有octo-drive仓,前端`drive/search` POST, highlights.name/body双字段, content_meta.extractor走Tika+OS)。doc-indexer(`octo-doc-indexer:v1.1.0`内网镜像)和drive-indexer(`octo-drive-indexer:v0.1.0`内网镜像)是各自模块的私有组件,不在开源octo-search-indexer仓中。
Search(全文搜索)是OCTO内部版的跨模块全文检索基础设施,采用多管道异步索引架构——消息搜索由octo-server `modules/messages_search`模块+开源octo-search-indexer(es-indexer,仅消息附件Tika抽取)处理;Docs和Drive各有独立的私有索引组件(doc-indexer/drive-indexer内网镜像),Drive有独立搜索后端(私有octo-drive仓)。证据支持"分别查再合并"形态,❌统一大索引未找到证据。覆盖:文本类消息+文件名+文件内容(Tika抽正文);图片OCR/语音ASR/卡片/系统消息入索引=未证实。权限:查询时权限校验(结合成员/频道可见性),非独立索引,设计上避免越权。indexer独立服务异步消费,延迟秒级到分钟级属正常。Bot搜索:`POST /v1/botfather/messages/search`以Bot主人身份搜索(OBO模式)。⚠️权重排序/merge逻辑/精确SLA/doc-indexer私有细节=私有仓待确认。Profile开关分三层:`search`(核心消息)、`doc-index`(文档索引,docs私有组件)、`drive-index`(网盘索引,Drive独立搜索后端组件)。
一、模块定位(一句话口径)
全文搜索 = OCTO的异步跨模块检索基础设施:多管道索引架构——
1. 消息类索引:octo-server `modules/messages_search` 模块处理查询 + 开源octo-search-indexer(es-indexer)消费消息附件抽取
2. 文档类索引:doc-indexer(`octo-doc-indexer:v1.1.0`内网镜像,docs私有组件)处理云文档正文
3. 网盘类索引:🔴Q6确认Drive有独立搜索后端(私有octo-drive仓),drive-indexer(`octo-drive-indexer:v0.1.0`内网镜像)为Drive私有组件;开源octo-search-indexer不处理Drive文件
查询形态:证据支持"分别查再合并"(消息与doc/drive各自索引查询后合并结果),❌统一大索引未找到证据,❌两索引merge具体逻辑=未找到证据(私有仓待确认)
覆盖范围(Q5源码确认):
- ✅ 文本类消息 + 文件名 + 文件内容(Tika抽正文)
- ❓ 图片OCR、语音ASR自动入库可搜索:未找到证据(未见OCR/ASR→search写入链路)
- ❓ 卡片/系统消息是否入索引:未找到证据
权限控制方向(Q5确认):✅查询时权限校验(结合成员/频道可见性),非独立索引,设计上避免越权;⚠️具体join/字段细节不做断言,以私有仓为准
异步特性(Q5确认):indexer独立服务、异步消费,延迟秒级到分钟级属正常;❌doc/drive是否经Kafka/精确SLA/丢失风险待私有仓确认
Bot搜索确认:`POST /v1/botfather/messages/search` 以Bot主人身份搜索(OBO模式,权限等同主人),octo-cli使用
二、部署与基础设施硬事实(来源:内部部署仓库配置 + 开源文档 + Q5源码确认)
2.1 核心基础设施(search profile)
search-opensearch(搜索引擎)
| 项目 | 事实 | 来源 |
|---|---|---|
| 镜像 | octo-search-opensearch-ik:2.17.0(本地构建,baked in analysis-ik中文分词插件) |
docker-compose |
| 容器端口 | 9200(HTTP API)+ 9300(Transport,容器内通信) | docker-compose |
| 宿主机端口 | 127.0.0.1:29200(loopback默认) | docker-compose |
| 存储卷 | opensearch-data → /usr/share/opensearch/data |
docker-compose / Helm pvc |
| JVM | -Xms512m -Xmx512m(默认,生产需调大) |
docker-compose |
| 安全 | DISABLE_SECURITY_PLUGIN=true(本地简化模式,🔴生产需启用,见SR-09) |
docker-compose |
| 分词器 | 索引使用ik_max_word(细粒度分词),查询使用ik_smart(智能分词) |
v1.8 mapping文档 |
| 依赖 | search-ensure(一次性创建index+alias) | docker-compose depends_on |
| 索引分组 | 索引名 | Alias(读) | 内容 | 上线版本 | 可信度 |
|---|---|---|---|---|---|
| 消息类索引 | octo-message |
wukongim-messages-read |
即时消息全文索引(文本类消息+文件名+文件内容) | 初始版本 | high(开源文档+部署+Q5三印证)⚠️图片caption/合并转发内容/卡片/系统消息是否入索引需私有仓确认 |
| 文档/网盘类索引 | octo-doc |
octo-doc-read |
云文档正文内容索引(Tika抽正文) | Web v2026.08.03 | high(部署确认+Q5确认) |
| 文档/网盘类索引 | octo-drive |
(待确认) | 网盘文件正文索引(Tika抽正文,文件正文可搜Server PR#554, 2026-07-08) | Web v2026.08.24 | high(部署确认+Q5确认) |
🔴 Q5纠偏:以上分属两套索引(消息类 vs 文档/网盘类),非统一大索引。查询形态为"分别查再合并",❌两索引merge具体逻辑=未找到证据(私有仓待确认,见§八私有仓边界)。
⚠️ 开源文档中消息索引名模式为`wukongim-messages-*`(带时间后缀、支持滚动),部署配置ensure job创建名为`octo-message`的索引。命名差异可能是内部版改名或版本不同,待确认(SR-04)。
search-kafka(事件总线)
| 项目 | 事实 | 来源 |
|---|---|---|
| 镜像 | apache/kafka:3.8.0(KRaft单节点模式,无ZooKeeper) |
docker-compose |
| 容器端口 | 9092(PLAINTEXT内部)+ 9093(CONTROLLER)+ 29092(EXTERNAL) | docker-compose |
| 宿主机端口 | 127.0.0.1:29092(loopback默认) | docker-compose |
| 存储卷 | kafka-data → /var/lib/kafka/data |
docker-compose / Helm pvc |
| Topic管理 | KAFKA_AUTO_CREATE_TOPICS_ENABLE=false(Topic必须预创建) |
docker-compose |
| Topic | 管道 | 消费者 | 配套队列 | 来源 |
|---|---|---|---|---|
octo.message.v1 |
消息索引 | 开源octo-search-indexer(es-indexer),consumer group file-extractor |
.dlq(死信) |
search-kafka-init + Q6确认 |
octo.docindex.v1 |
文档索引 | doc-indexer(docs私有组件) | .retry(重试)+ .dlq(死信) |
doc-index-kafka-init |
octo.driveindex.v1 |
网盘索引 | drive-indexer(Drive私有搜索后端组件);⚠️Q6确认开源仓不消费此topic | .retry.v1(重试)+ .dlq.v1(死信) |
drive-index-kafka-init + Q6 |
⚠️ Q6更新:`octo.message.v1`→开源es-indexer确认[high](payload.type=8→Tika→OS,Tika黑名单.mp4/.zip/.jpg等,内容截断256KB,DLQ,tombstone+MySQL join);`octo.driveindex.v1`开源仓零命中——drive-indexer是私有octo-drive仓组件,索引延迟/删除同步=未可见;`octo.docindex.v1`消费者doc-indexer是内网镜像,属docs私有组件。
octo-search-indexer / es-indexer(消息附件索引器,Q6确认仅管消息附件)
| 项目 | 事实 | 来源 |
|---|---|---|
| 镜像 | mininglamposs/octo-search-indexer:latest(开源镜像) |
docker-compose |
| 服务名 | es-indexer(历史命名);🔴Q6纠偏:此开源仓仅处理消息附件抽取,doc/drive不走此仓 |
docker-compose + Q6 |
| 性质 | 独立服务、异步消费,秒级到分钟级延迟正常 | Q5/Q6 |
| Profile | search(消息索引);不处理doc-index/drive-index |
docker-compose + Q6 |
| 消费Topic | octo.message.v1(仅此一个topic),consumer group file-extractor,DLQ: octo.message.v1.dlq |
docker-compose env + Q6 |
| 处理逻辑 | payload.type=8→下载消息附件→Apache Tika→OS partial update写payload.file.content |
Q6源码确认 |
| Tika黑名单 | .mp4/.zip/.jpg等媒体/压缩/图片格式排除 | Q6 |
| 内容截断 | 256KB | Q6 |
| 错误处理 | DLQ错误分类;tombstone+读时MySQL join过滤revoke/delete | Q6 |
| 写入索引 | octo-message,BATCH_SIZE=500 |
docker-compose env |
| 存储卷 | search-dlq-spill(DLQ spill持久化,crash-resumable) |
docker-compose |
| 核心开关 | ES_INDEXER_ENABLED=true |
docker-compose env |
| 依赖 | search-kafka-init, search-opensearch, search-ensure | docker-compose depends_on |
🔴 Q6纠偏:doc-indexer(`octo-doc-indexer:v1.1.0`内网镜像)和drive-indexer(`octo-drive-indexer:v0.1.0`内网镜像)不在开源octo-search-indexer仓中。es-indexer(开源镜像`mininglamposs/octo-search-indexer:latest`)仅负责消息附件抽取。doc-indexer是docs模块的私有组件,drive-indexer是Drive模块私有搜索后端的组件(私有octo-drive仓)。
2.2 搜索生产者(Producer侧,两种模式互斥)
| 模式 | 组件 | Profile | 适用场景 | 来源 |
|---|---|---|---|---|
| 内置模式(默认) | octo-server内置searchetl模块(TS_KAFKA_ON=true) |
search-producer不启用 |
Docker Compose单机部署 | docker-compose / octo-server env |
| 独立模式 | search-producer容器(同octo-search-indexer镜像,entrypoint为searchetl-producer) |
search-producer |
K8s生产部署(独立扩缩容) | docker-compose |
| 变量 | 说明 |
|---|---|
TS_KAFKA_ON |
Kafka搜索producer开关(true启用) |
TS_KAFKA_BROKERS |
Kafka broker地址 |
TS_KAFKA_TOPIC |
消息Kafka topic(默认octo.message.v1) |
- 新消息经WuKongIM gRPC webhook到达octo-server后,searchetl模块将消息变更事件写入Kafka
- MySQL分片表维护ETL游标(`octo_etl_es_cursor`表),保证at-least-once投递
- Producer从MySQL增量读取新消息,序列化为OpenSearch文档格式发往Kafka
⚠️ doc-indexer(docs私有组件)和drive-indexer(Drive私有搜索后端组件)的producer侧逻辑归属及是否实际经Kafka=私有仓待确认(SR-06)。部署配置显示docs-backend有`KAFKA_BROKERS`+`DOCINDEX_KAFKA_TOPIC`,drive有`DRIVE_KAFKA_DISABLED`开关,推测producer分别内置于docs-backend和octo-drive。Q6确认开源octo-search-indexer仓不消费doc/drive topic。
2.3 一次性工具(search-tools profile)
| 工具 | 功能 | 来源 |
|---|---|---|
| search-cursor-seed | 将octo_etl_es_cursor种子设置到每个消息分片表的MAX(id),避免producer启动时回放全部历史消息(仅从seed位置之后开始增量同步) |
docker-compose / search-dev doc |
| search-backfill | 一次性历史数据回填:从MySQL全量扫描历史消息,绕过Kafka直接写入OpenSearch,带reconcile校验(用于首次初始化/索引重建) | docker-compose / search-dev doc |
2.4 文档索引管道(doc-index profile,依赖docs+search)
doc-indexer(文档索引器——docs模块私有组件,内网镜像v1.1.0)
🔴 Q6更新:doc-indexer使用内网镜像`octo-doc-indexer:v1.1.0`,是docs模块的私有索引组件,不在开源octo-search-indexer仓中。其源码/实现细节属docs-backend私有仓。
| 项目 | 事实 | 来源 |
|---|---|---|
| 镜像 | hub2.intra.mlamp.cn/octo/octo-doc-indexer:v1.1.0(pin版) |
docker-compose / Helm |
| 容器端口 | 3100(HTTP/readyz健康检查) | docker-compose |
| Profile | doc-index(需同时启用docs+search) |
docker-compose |
| Kafka消费(部署可见) | topic: octo.docindex.v1,group: doc-indexer;有retry/dlq队列 |
docker-compose |
| OpenSearch写入 | index: octo-doc,alias: octo-doc-read |
doc-index-ensure |
| 文件解析 | 文档正文抽取(是否经Tika待确认,drive明确经Tika) | 部署配置 |
| 上线版本 | Web v2026.08.03(云文档正文搜索上线) | 产品管家确认 |
| 依赖 | doc-index-kafka-init, doc-index-ensure | docker-compose depends_on |
doc-index初始化服务
| 服务 | 功能 |
|---|---|
| doc-index-kafka-init | 创建octo.docindex.v1 / .retry / .dlq 三个Kafka topic |
| doc-index-ensure | 创建OpenSearch octo-doc index + octo-doc-read alias |
2.5 网盘索引管道(drive-index profile,依赖drive+search)
tika(文档内容解析服务——Apache Tika)
| 项目 | 事实 | 来源 |
|---|---|---|
| 镜像 | hub2.intra.mlamp.cn/octo/tika:3.3.0.0(基于Apache Tika 3.3.0.0) |
docker-compose + Q5/Q6确认 |
| 容器端口 | 9998 | docker-compose |
| 功能 | 抽取文件正文供索引(供消息附件es-indexer和drive-indexer使用;Q6确认es-indexer也走Tika做消息附件抽取) | Q5/Q6 |
| Profile | drive-index(drive-indexer依赖);es-indexer内置Tika客户端逻辑 |
docker-compose + Q6 |
⚠️ Tika支持的文件格式完整清单、256KB内容截断(Q6确认es-indexer截断策略)和是否支持OCR待确认(SR-03)。Q5/Q6明确标注:图片OCR自动入库搜索=未找到证据。
drive-indexer(网盘索引器——Drive独立搜索后端组件,私有octo-drive仓,Q6确认)
🔴 Q6 P0纠偏:drive-indexer是Drive私有搜索后端组件(内网镜像`octo-drive-indexer:v0.1.0`),属私有octo-drive仓,不在开源octo-search-indexer仓中。开源仓全仓0命中`octo.driveindex.v1`消费逻辑。前端`drive/search` POST(highlights.name/body双字段, content_meta.extractor走Tika+OS)由Drive独立搜索后端服务。索引延迟/删除同步机制=私有仓不可见。
| 项目 | 事实 | 来源 |
|---|---|---|
| 镜像 | hub2.intra.mlamp.cn/octo/octo-drive-indexer:v0.1.0(pin版) |
docker-compose / Helm |
| 容器端口 | 3200 | docker-compose |
| Profile | drive-index(需同时启用drive+search) |
docker-compose |
| Kafka消费(部署可见) | topic: octo.driveindex.v1,group: octo-drive-indexer;有retry/dlq队列 |
docker-compose |
| OpenSearch写入 | index: octo-drive |
drive-index-ensure |
| Tika集成 | TIKA_URL=http://tika:9998(文件文本提取,Q5确认) |
docker-compose env + Q5 |
| SSRF防护🔴 | ALLOWED_DOWNLOAD_HOSTS / SSRF_ALLOW_LOOPBACK=false |
docker-compose env |
| 上线版本 | Web v2026.08.24(网盘文件正文搜索上线);文件正文可搜Server PR#554(2026-07-08) | 产品管家确认 |
| 依赖 | drive-index-kafka-init, drive-index-ensure, tika | docker-compose depends_on |
drive-index初始化服务
| 服务 | 功能 |
|---|---|
| drive-index-kafka-init | 创建octo.driveindex.v1 / .retry.v1 / .dlq.v1 三个Kafka topic |
| drive-index-ensure | 等待Tika就绪后创建OpenSearch octo-drive index |
2.6 octo-server查询侧集成
| 端点 | 功能 | 可信度 |
|---|---|---|
POST /v1/messages/_search |
消息全文搜索,按发送者/时间过滤,三种排序(时间降序/升序/相关性) | high(开源文档)⚠️权重排序打分逻辑=私有仓待确认 |
POST /v1/messages/_search_media |
消息媒体搜索(图片+视频),无keyword | high(开源文档) |
POST /v1/messages/_search_files |
消息文件搜索,keyword可选(搜文件名/caption) | high(开源文档) |
POST /v1/messages/_search_all |
消息全局搜索(文本+文件+媒体+富文本+转发,浏览模式含图片视频) | high(开源文档)⚠️是否跨索引merge doc/drive结果=私有仓待确认 |
POST /v1/search/global |
旧版全局搜索(透传wukongim usersearch,保留并存,待下线) | high(开源文档) |
POST /v1/botfather/messages/search |
Bot消息搜索API——以Bot主人身份搜索(OBO模式,权限等同主人),octo-cli使用 | high(Q5+前序产品管家确认) |
| 特征 | 说明 |
|---|---|
| Routing | 所有搜索按channelId路由(OS _routing.required: true),确保查询只命中对应分片 |
| IK中文分词 | 索引用ik_max_word(细粒度),查询用ik_smart(智能) |
| Highlight | 命中关键词高亮(标签),fragment_size=120 |
| Cursor分页 | search_after+HMAC防篡改cursor,支持无限滚动,默认pageSize=20,最大100 |
| 权限控制✅ | Q5确认方向:查询时权限校验(结合成员/频道可见性),非独立索引,设计上避免越权;消息搜索解散状态authz校验;撤回/删除/用户级删除/清空会话等信号由octo-server端post-filter兜底(fail-closed);⚠️具体join/字段细节不做断言 |
| Space隔离 | p2p搜索按spaceId双维度过滤(待indexer v1.9补充spaceId字段后完全生效) |
| 限流 | 5 QPS / 20桶 per loginUID |
| sender JOIN | 发送者姓名/头像通过octo-server JOIN user/group_member表(LRU cache),不存OS |
| 撤回/删除处理 | v1.10计划由indexer做partial update更新revoked/isDeleted字段;当前由server端post-filter兜底 |
| 权重排序🔴 | ⚠️ 相关性排序打分逻辑/boost权重=私有仓待确认,开源文档仅见payload.text.content权重^3,其余字段权重不可断言 |
三、多管道索引架构总览(Q5纠偏+Q6 Drive独立搜索后端确认)
┌─────────────────────────────────────────────┐
│ 数据写入侧(Producers) │
├─────────────────────────────────────────────┤
新消息 ──► octo-server(内置searchetl) ─TS_KAFKA_ON─┐ │
(或独立search-producer,K8s模式) │ │
▼ │
文档变更 ──► docs-backend ──KAFKA_BROKERS──► search-kafka:9092 │
(docs私有producer/是否经Kafka待确认) (消息管道确认) │
网盘文件变更 ──► octo-drive ──DRIVE_KAFKA──► (doc/drive=私有仓) │
(Drive私有搜索后端producer/待确认) │
└────────────────────────────────┬─────────────┘
│
┌──────────────────────────────────────────┼──────────────────┐
│ 索引消费侧(Q6确认:三管道分治) │ │
│ ▼ │
│ ┌───────────────────────┐ 消息类索引(开源,Q6确认) │
│ │ es-indexer │──► octo-message (OpenSearch) │
│ │(开源octo-search- │ (wukongim-messages-read) │
│ │ indexer:latest) │ │
│ │ 仅消息附件! │ Tika黑名单:mp4/zip/jpg │
│ │ octo.message.v1消费 │ 截断256KB/DLQ/tombstone │
│ └───────────────────────┘ │
│ │
│ ┌───────────────────────┐ 文档类索引(docs私有组件) │
│ │ doc-indexer │──► octo-doc (OpenSearch) │
│ │ (内网v1.1.0/docs私有) │ (octo-doc-read alias) │
│ │ octo.docindex.v1消费 │ ⚠️实现细节=私有仓 │
│ └───────────────────────┘ │
│ │
│ ┌───────────────────────┐ 网盘类索引(Drive独立搜索后端) │
│ │ drive-indexer ──Tika──┼──► octo-drive (OpenSearch) │
│ │ (内网v0.1.0/Drive私有)│ ┌──────┐ │
│ │ octo.driveindex.v1消费│ │:9998 │ Q6确认独立后端 │
│ │ ⚠️索引延迟/删除=私有 │ └──────┘ 不在开源仓 │
│ └───────────────────────┘ │
│ 🔴开源octo-search-indexer仓不处理doc/drive!(Q6 P0纠偏) │
└────────────────────────────────┬────────────────────────────┘
│
┌────────────────┼─────────────────────────────────────────────┐
│ 初始化/工具 │ │
│ cursor-seed: 设置消息增量起点 │
│ backfill: 消息历史回填(直写OS,仅消息) │
│ kafka-init: 预创建三个管道topics │
│ ensure: 创建index+alias(三个索引分别创建) │
└───────────────────────────────────────────────────────────────┘
│
┌────────────────┼─────────────────────────────────────────────┐
│ 查询侧(Query——分别查再合并,Q5确认方向)│ │
│ ▼ │
│ octo-server:8090 │
│ ┌─────────────────────────────────────────────┐ │
│ │ 1. 查消息类索引(octo-message) │ │
│ │ 2. 查文档/网盘类索引(octo-doc/octo-drive) │ │
│ │ 3. 合并结果(⚠️merge逻辑=私有仓待确认) │ │
│ └─────────────────────────────────────────────┘ │
│ ├── /v1/messages/_search │
│ ├── /v1/messages/_search_media │
│ ├── /v1/messages/_search_files │
│ ├── /v1/messages/_search_all │
│ ├── /v1/botfather/messages/search (Bot OBO) │
│ ├── /v1/search/global (旧) │
│ ├── [云文档搜索] ✅功能上线(Web08.03) │
│ ├── [网盘文件搜索] ✅功能上线(Web08.24) │
│ └── [跨索引全局搜索] ⚠️merge逻辑待确认 │
│ 权限过滤(查询时校验,成员/频道可见性)/sender JOIN/ post-filter │
│ ⚠️异步延迟:秒级到分钟级属正常 │
└────────────────────────────────┬────────────────────────────┘
│
▼
Web / iOS / Android
四、已确认能力(Q5+Q6源码确认+开源文档+部署硬事实印证)
4.1 三管道索引搜索覆盖(Q5+Q6确认)
| 索引分组 | 索引 | 索引组件 | 内容 | Web上线 | 可信度 |
|---|---|---|---|---|---|
| 消息类 | octo-message | 开源es-indexer(octo-search-indexer仓) | 文本类消息 + 文件名 + 消息附件内容(Tika, 截断256KB,黑名单) | 初始版本 | high |
| 文档类 | octo-doc | doc-indexer(docs私有组件,内网v1.1.0) | 云文档正文 | v2026.08.03 | high(功能上线确认)/ low(实现细节私有) |
| 网盘类 | octo-drive | Drive独立搜索后端(drive-indexer私有octo-drive仓,内网v0.1.0,Tika) | 网盘文件正文(drive/search, highlights.name/body) |
v2026.08.24 | high(前端API确认)/ low(后端实现私有) |
- ❌ 图片OCR自动入库可搜索(未见OCR→search写入链路)
- ❌ 语音ASR自动入库可搜索(未见ASR→search写入链路)
- ❌ 卡片消息是否入索引
- ❌ 系统消息是否入索引
⚠️ 开源开发文档中提及"图片caption/name、合并转发内容"入索引,但Q5源码确认范围仅覆盖"文本类消息+文件名+文件内容",caption/转发内容是否入索引降级为待确认。
4.2 消息全文搜索技术特征(开源文档证实,Q5标注待确认项)
- 文本消息全文检索(IK中文分词,支持相关性排序;⚠️具体打分权重=私有仓待确认)
- 搜索范围覆盖:消息正文(payload.text.content,权重^3为开源文档可见)、文件名
- 按频道(私聊/群聊/Thread)隔离搜索,routing保证分片局部性
- 过滤维度:发送者、时间范围
- 三种排序:时间降序(默认)、时间升序、相关性(⚠️相关性打分=私有仓待确认)
- 搜索结果关键词高亮(
标签),fragment_size=120 - 媒体搜索(图片/视频):时间线浏览媒体文件
- 文件搜索:按文件名搜索消息附件
- Cursor翻页(HMAC防篡改),默认pageSize=20,最大100
- 5 QPS/用户限流
- 图片caption/合并转发内容/富文本是否入消息索引(Q5后降级)
_search_all是否跨两套索引merge doc/drive结果
4.3 权限控制(Q5方向确认,medium可信度)
- 查询时权限校验(结合成员/频道可见性),非独立索引,设计上避免越权
- 消息搜索解散状态authz校验(前序确认)
- 撤回/删除/用户级删除等可见性信号由octo-server端post-filter兜底(fail-closed)
- Space维度隔离
4.4 Bot搜索——OBO模式(前序产品管家确认,high)
- API端点:
POST /v1/botfather/messages/search - 以Bot主人身份搜索(OBO, On-Behalf-Of模式):权限等同Bot主人
- 使用方:octo-cli
- ⚠️ 文档/网盘的Bot API待验证(SR-07)
4.5 异步管道特性(Q5+Q6更新)
- es-indexer是独立服务、异步消费,仅消费
octo.message.v1 - 延迟:秒级到分钟级属正常(非严格实时同步)
- 消息管道:MySQL→Kafka→OpenSearch,BATCH_SIZE=500
- Tika抽取:黑名单(.mp4/.zip/.jpg等) + 256KB截断 + DLQ错误分类 + tombstone+MySQL join过滤
- DLQ死信队列保证消费失败可追踪(spill持久化crash-resumable)
- cursor-seed保证producer重启后不回放全量历史
- backfill支持消息历史数据全量回填(绕过Kafka直写OS,带reconcile校验)
- 精确延迟SLA(P95/P99)
- 消息丢失风险/数据一致性保证
- doc-indexer(docs私有)/drive-indexer(Drive私有后端)的完整管道(是否经Kafka、延迟、DLQ、删除同步)
- Drive搜索后端索引延迟、删除同步机制(Q6标注私有仓不可见)
八、🔴私有仓边界声明(Q5+Q6更新)
以下逻辑位于各模块私有仓/私有配置中,当前可读开源源码(octo-server/modules/messages_search + octo-search-indexer开源仓 + octo-deployment)无法确认,知识库不做断言:
| 编号 | 私有仓不可见项 | 影响 | 标注 |
|---|---|---|---|
| PRIV-01 | 权重/排序打分逻辑 | 相关性排序结果、字段boost权重 | 文档中仅开源可见的payload.text.content ^3为确认 |
| PRIV-02 | 跨索引查询merge逻辑 | 全局搜索(消息+doc+drive合并排序) | "分别查再合并"为形态确认,具体算法未知 |
| PRIV-03 | doc/drive管道是否经Kafka、精确延迟SLA、丢失风险、Drive索引删除同步 | 数据一致性保证、运维SLA承诺 | 消息管道Kafka确认[high];doc/drive部署有topic但消费者是私有组件;Drive搜索后端索引延迟/删除同步=Q6标注私有仓 |
| PRIV-04 | 卡片/系统消息是否入索引 | 搜索覆盖范围 | Q5:未找到证据 |
| PRIV-05 | 图片OCR/语音ASR是否自动入库搜索 | 多媒体搜索能力 | Q5:未找到证据(未见OCR/ASR→search写入链路) |
| PRIV-06 | 权限过滤具体实现(join vs 过滤字段)+是否存在已知越权风险 | 数据安全 | Q5:查询时校验方向确认,具体实现细节与越权风险未完全取证,不能断言零风险 |
| PRIV-07🔴 | octo-search-indexer开源仓确认不处理doc/drive | 架构划分 | ✅Q6确认:开源仓仅消费octo.message.v1做消息附件抽取;doc-indexer/drive-indexer是内网镜像私有组件 |
五、待确认项汇总(知识库行动项)
| 编号 | 待确认项 | 确认方式 | 优先级 | 安全敏感 | 来源 |
|---|---|---|---|---|---|
| SR-01🔴 | 权重/排序打分逻辑:各字段boost权重、相关性算法、排序策略 | 私有仓/产品管家 | P0 | 否 | Q5 PRIV-01 |
| SR-02🔴 | 两索引merge逻辑:跨索引(消息+doc+drive)全局搜索如何合并排序?是否有统一入口? | 私有仓/产品管家/实测 | P0 | 否 | Q5 PRIV-02 |
| SR-03🔴 | 精确延迟SLA/丢失风险/doc-drive Kafka确认:消息发出到可搜P95延迟?doc/drive是否实际经Kafka?数据丢失风险/一致性保证? | 私有仓/运维/压测 | P0 | 否 | Q5 PRIV-03 |
| SR-04 | 索引命名与生命周期:内部版索引名是octo-message还是wukongim-messages-*滚动模式?是否使用ISM策略(hot-warm-cold/自动过期)? |
查search-ensure job/OS模板 | P2 | 否 | 前序 |
| SR-05🔴 | 卡片/系统消息/OCR/ASR入索引:卡片消息、系统消息是否入索引?图片OCR/语音ASR是否有写入链路? | 私有仓/产品管家 | P1 | 否 | Q5 PRIV-04/05 |
| SR-06 | Tika格式清单:Tika支持的文件格式完整清单?大文件截断策略? | 查tika配置/drive-indexer源码 | P1 | 否 | 前序 |
| SR-07 | 云文档/网盘搜索权限模型:文档搜索和网盘搜索的权限过滤细节(具体join/字段)?解散/离职/分享链接等边界场景? | 私有仓/产品管家 | P1 | 是(数据越权风险) | Q5+前序 |
| SR-08 | doc/drive producer侧:docs-backend和octo-drive如何发送变更事件?docs的SEARCH_INDEX_ENABLED/SEARCH_ENABLED开关具体作用? | 查docs-backend/octo-drive源码 | P2 | 否 | 前序 |
| SR-09 | 文档/网盘Bot API:除/v1/botfather/messages/search外,文档/网盘是否有对应的Bot搜索API? |
查octo-server bot路由源码 | P2 | 否 | 前序 |
| SR-10 | 端支持范围:iOS/Android是否支持文档/网盘全文搜索和全局搜索?还是仅Web端? | 产品管家/实测 | P2 | 否 | 前序 |
| SR-11 | OpenSearch安全配置🔴:生产环境是否启用Security插件(用户名密码/TLS)? | 查部署文档/安全设计 | P1 | 是(基础设施安全) | 前序 |
| SR-12 | drive-indexer SSRF防护范围🔴:ALLOWED_DOWNLOAD_HOSTS精确范围?是否限制为MinIO内网地址? | 查drive-indexer源码/安全设计 | P1 | 是(SSRF风险面) | 前序 |
| SR-13 | 搜索高级语法:精确匹配(引号)、排除词(-)、Boolean(AND/OR)、特殊语法?搜索历史/热门搜索? | 实测/查前端源码 | P3 | 否 | 前序 |
| SR-14 | Kafka/OS生产部署建议:Kafka多节点集群?JVM内存/分片/副本数推荐值?消息持久化备份策略? | 查部署文档/问运维 | P3 | 否 | 前序 |
| SR-15 | 搜索可用性降级:OpenSearch/Kafka不可用时octo-server搜索API如何降级? | 查octo-server源码 | P3 | 否 | 前序 |
| SR-16🔴 | 权限过滤具体实现/越权风险:查询时权限校验是join权限表还是过滤查询字段?是否存在已知越权漏洞?设计上避免越权但不能断言零风险 | 私有仓/安全审计 | P1 | 是(数据越权风险) | Q5 PRIV-06 |
- SR-07(文档/网盘搜索权限):Q5确认"查询时权限校验、非独立索引、设计上避免越权"方向,但具体join/字段细节在私有仓,需同等确认防止越权。
- SR-11(OS安全配置):当前部署默认关闭Security插件,生产环境必须启用认证和TLS。
- SR-12(drive-indexer SSRF):
SSRF_ALLOW_LOOPBACK=false说明设计者意识到了SSRF风险,需确认ALLOWED_DOWNLOAD_HOSTS精确范围。
六、与其他模块的关系
| 模块 | 关系 | 状态 | 可信度 |
|---|---|---|---|
| octo-server | 查询统一入口;内置消息搜索producer(searchetl);modules/messages_search处理消息类索引查询;权限过滤(查询时校验确认)/sender JOIN/post-filter;限流;Bot OBO搜索API |
✅ 开源文档+Q5确认 | high(查询侧)/ medium(权限细节) |
| WuKongIM | 消息源头(gRPC webhook→octo-server→Kafka) | ✅ 硬事实 | high |
| MySQL(octo主库) | 消息Producer增量读取分表;维护ETL游标(octo_etl_es_cursor);server端post-filter;历史回填backfill源 |
✅ 硬事实+开源文档 | high |
| Kafka | 消息管道事件总线确认[high];doc/drive管道是否经Kafka部署可见但Q5标私有仓待确认;DLQ机制可见 | ✅(消息)/ ⚠️(doc/drive) | high / medium |
| OpenSearch | 全文索引存储+查询引擎(IK中文分词);两套索引分组:消息类(octo-message)+文档/网盘类(octo-doc/octo-drive);read alias查询模式 | ✅ 硬事实+Q5确认 | high |
| octo-search-indexer(开源仓)🔴 | Q6确认:开源仓(es-indexer镜像mininglamposs/octo-search-indexer:latest)仅处理消息附件抽取(octo.message.v1 topic, consumer group file-extractor, Tika黑名单/256KB截断/DLQ/tombstone);不处理doc/drive文件索引,无octo.driveindex.v1消费逻辑 |
✅ Q6 P0纠偏确认 | high(开源仓范围) |
| docs-backend | 文档变更事件来源;文档正文搜索Web v2026.08.03上线;doc-indexer是docs私有组件;producer细节待确认 | ⚠️ Q6更新 | medium |
| doc-indexer🔴 | docs模块私有组件(内网镜像octo-doc-indexer:v1.1.0),不在开源octo-search-indexer仓;文档Kafka消费者→OpenSearch octo-doc索引;实现细节属docs私有仓 |
⚠️ Q6更新 | medium(部署可见)/ low(实现细节私有) |
| octo-drive | 网盘文件变更事件来源;网盘文件正文搜索Web v2026.08.24上线;Q6确认Drive有独立搜索后端(私有octo-drive仓) | ✅ Q6确认 | high(独立后端确认)/ low(实现细节私有) |
| drive-indexer🔴 | Drive独立搜索后端组件(内网镜像octo-drive-indexer:v0.1.0),不在开源octo-search-indexer仓,属私有octo-drive仓;网盘Kafka消费者→Tika→OpenSearch octo-drive;drive/search POST由Drive独立后端服务;索引延迟/删除同步=私有仓不可见 |
✅ Q6 P0纠偏确认 | high(部署+前端API确认)/ low(实现私有) |
| Apache Tika | 文件正文抽取服务(:9998),供es-indexer(消息附件)和drive-indexer(网盘文件)使用;镜像hub2.intra.mlamp.cn/octo/tika:3.3.0.0;es-indexer确认黑名单/256KB截断 |
✅ Q5+Q6确认 | high |
| Summary | Summary直接读MySQL消息(MESSAGE_FETCH_BACKEND=mysql),不依赖搜索服务 | ✅ Summary模块部署硬事实 | high |
| Bot/octo-cli | Bot通过/v1/botfather/messages/search以主人身份搜索(OBO模式);文档/网盘Bot API待确认 |
✅ 产品管家确认 | high |
| MinIO | drive-indexer从MinIO octo-drive bucket下载文件供Tika解析;SSRF范围待确认 | ⚠️ 配置推断 | medium |
七、版本记录
- v0.1(2026-09-21):基于内部部署仓库硬事实 + 开源octo-server搜索模块文档(messages-search/)新建;消息搜索部分high,doc/drive管道low
- v0.2(2026-09-21):格式对齐标准——frontmatter confidence=medium;部署硬事实各表增加"来源/可信度"列;已确认能力按可信度分级;待确认项SR-01~SR-14;模块关系表增加可信度列;三层管道架构图
- v0.3(2026-09-21):基于完整产品管家回答回填——三类搜索覆盖确认(消息+云文档08.03+网盘08.24);文件正文可搜PR#554;架构确认(octo-search-indexer独立服务, MySQL→Kafka→OS全链路, 历史回填+DLQ);权限控制确认(解散authz);Bot OBO搜索确认;confidence升medium-high
- v0.4(2026-09-22):🔴Q5源码确认回填+P0纠偏——①架构纠偏:从"统一大索引近实时"修正为"两套索引(消息类vs文档/网盘类),分别查再合并",统一大索引❌未找到证据;②octo-search-indexer独立仓确认:doc/drive走独立仓(含Apache Tika文件正文抽取);③异步延迟修正:从"NRT近实时"修正为"独立服务异步消费,秒级到分钟级延迟正常",非严格实时同步;④Apache Tika确认:文件正文抽取经Tika(Q5明确);⑤权限方向细化:查询时权限校验(结合成员/频道可见性),非独立索引,设计上避免越权;具体join/字段细节不做断言;⑥覆盖范围修正:已确认=文本类消息+文件名+文件内容(Tika);OCR/ASR/卡片/系统消息=未找到证据;图片caption/合并转发内容降级为待确认;⑦新增§八私有仓边界声明:PRIV-01~05(权重排序/merge逻辑/Kafka-SLA/卡片系统消息/OCR-ASR);⑧待确认项重构,SR-01~03升P0(私有仓核心项),新增SR-05(OCR/ASR/卡片),重新编号至SR-15;⑨架构图更新为"两套索引"分组,标注merge逻辑待确认;⑩status改为draft,confidence为medium,版本v0.4
- v0.5(2026-09-22):🔴Q6 P0纠偏——octo-search-indexer仅管消息附件,Drive有独立搜索后端——①核心纠偏:从"文档/网盘走独立octo-search-indexer仓"修正为"开源octo-search-indexer仓(es-indexer)仅处理消息附件抽取"(
octo.message.v1/file-extractor/payload.type=8→Tika→OS/Tika黑名单.mp4|.zip|.jpg/256KB截断/DLQ/tombstone+MySQL join),❌开源仓无octo.driveindex.v1消费逻辑;②Drive独立搜索后端确认:drive/searchPOST/highlights.name+body/content_meta.extractor走Tika+OS,后端在私有octo-drive仓;③doc-indexer/drive-indexer归属修正:两者是内网镜像私有组件(octo-doc-indexer:v1.1.0/octo-drive-indexer:v0.1.0),不在开源octo-search-indexer仓中;④Tika用途更新:es-indexer也走Tika做消息附件抽取(不仅是drive-indexer);⑤Kafka Topics表更新:标注每个topic的消费者归属,开源仓仅消费octo.message.v1;⑥es-indexer表补充:新增Tika黑名单/256KB截断/错误处理等Q6确认细节;⑦架构图重绘:三管道分治(消息开源/doc私有/drive私有后端),醒目标注"开源仓不处理doc/drive";⑧覆盖范围表更新:从"两套索引"改为"三管道",标注各索引组件归属和可信度分档;⑨§八私有仓边界更新:新增PRIV-07,PRIV-03补充Drive索引删除同步;⑩模块关系表更新:octo-search-indexer/doc-indexer/drive-indexer/Tika/octo-drive行按Q6修正;⑪frontmatter更新(版本/last_updated/source新增Q6/confidence/octo_version);⑫头部新增P0纠偏2说明块