业务故事站
P2 Foundry

统一搜索与 actionctl:全平台找得到、命令行用得了

Nexus 统一搜索把"找得到"变成平台级能力:顶栏一个输入框,跨对象 / 指标 / 数据集 / 仪表盘 / Notebook 五类资产并行召回,RRF 融合排序,点一下跳到对应功能页;actionctl 命令行把"本体导出导入 / 数据集 / 任务 / 指标查询 / MCP 探活"带到终端。看完这 3 个故事,你就能在页面和命令行两端都顺畅干活。

业务分析师 平台管理员 数据工程师 Nexus 统一搜索 actionctl 共 3 个故事

能 / 不能速览

✅ 这个主题能做
  • GET /nexus/search?q=&scopes=&limit=:五 scope 并行召回 + RRF 1/(60+rank) 融合排序
  • 同 URI 跨 scope 分数累加、结果去重;limit 钳制(默认 20、上限 50)
  • 单 scope 故障容错:其余 scope 照常返回;全部失败才 500
  • fx_search_stats 热度表:每次成功搜索 best-effort 落 q + 命中数
  • Foundry 顶栏全局搜索框:300ms 防抖、URI→路由映射跳转
  • actionctl 7 子命令:login / ont export|import / dataset / task / metric query / mcp ping
⛔ 这个主题做不了
  • docs scope(AIP 知识文档)未注入,显式请求返回空不报错
  • 无向量索引:检索词全部走文本匹配(语义检索文本分 + 目录 LIKE)
  • 目录 LIKE 为朴素 %q% 子串匹配,无分词 / 同义词 / 拼音
  • 搜索跳转仅定位功能页,目标页暂无路由参数自动选中能力
  • actionctl metric query 的 --filters 只生成 eq 算子;单 base/token 配置 profile

适用角色

本主题面向三个角色:

  • 业务分析师:顶栏全局搜索找资产、点一下跳转功能页,是最主要的日常使用者。
  • 平台管理员 / 运维:用 actionctl 做本体导出导入、看数据集 / 任务、探活 MCP;统计热搜词。
  • 数据工程师:把对象定义导出进 Git(actionctl ont export),配合 Nexus 快速定位对象与指标。

AI 编码 agent 也常以 actionctl 做纯 HTTP 交互,不打开浏览器。

能力速览(能做什么)

五 scope 并行检索

objects(语义检索 + 对象级可见性)/ metrics(目录 LIKE)/ datasets / dashboards / notebooks(按 scope 查表),goroutine 并行、独立写 slot。

RRF 融合排序

score = Σ 1/(60+rank+1),同 URI 跨 scope 累加去重;同分按 type/title 字典序,输出确定性可测。

统一 URI 与跳转

object://foundry/<apiName>、metric://foundry/<name> 等稳定 URI 作为融合与跳转锚点,前端按前缀映射路由。

热度统计

每次成功搜索 best-effort 落 fx_search_stats(q + 融合去重后命中数),支撑"热门搜索 / 搜索质量"统计。

actionctl CLI

纯 HTTP client(flag 包,不引 cobra / products 包);配置三源优先级;JSON + --format table 双输出。

调整指南(怎么调整)

  • 收窄搜索范围:scopes=metrics,datasets 只搜指定类型;未知 scope 忽略,全非法回退默认五 scope。
  • 控制条数:limit 默认 20、上限 50,钳制发生在服务层;前端顶栏按 limit=8 取少量。
  • 跨类型找同资源:某数据集同时出现在 datasets 与 notebooks 时同 URI 累加置顶——这正是 RRF 的设计意图。
  • 命令行日常化:actionctl login 后 token 存 ~/.actionctl(0600);CI / 脚本用 ACTIONCTL_BASE / ACTIONCTL_TOKEN 环境变量注入。
  • 脚本判活:actionctl mcp ping 对未启用 MCP 返回 404 与退出码 1,可作部署探活信号。

做得好的场景

统一搜索 + CLI 让"找资产"和"操作资产"都开了快车道,特别适合以下场景:
  • 跨类型找资产:顶栏输入"订单",对象、数据集、工作簿一次出齐,不用逐个模块翻。
  • 找指标口径:输入"gmv"命中 total_gmv 指标,摘要显示描述或"口径: SUM(...)"。
  • 局部故障降级:objects 后端故障时其余 scope 照常返回,搜索不整体中断。
  • 运维脚本化:本体导出进 Git、看数据集、探活 MCP 全部命令行完成,可进 CI 流水线。

限制与不足

以下是明确的边界,使用前先知道:
  • docs scope 未注入:AIP 知识文档检索需跨产品适配,P0 只做 foundry 域;scopes=docs 返回空不报错。
  • 无向量索引:检索词全走文本匹配,未接入向量增强;中文分词 / 同义词只覆盖对象属性 synonyms。
  • metric 排序朴素:metrics 命中按目录 name 排序,非语义相关度;多指标命中时 RRF rank 未必反映真实相关度。
  • 跳转不自动选中:全局搜索跳到功能页,目标页暂无"按路由参数自动选中"能力(changelog 遗留)。
  • 热度表无 retention:fx_search_stats 只增不清理,高并发下会持续累积行数。
  • actionctl 能力边界:只覆盖运维场景(本体 / 数据集 / 任务 / 指标 / MCP),建模与 Action 设计仍在 Web 端;--filters 仅 eq 算子。

场景故事

故事 1 顶栏一个输入框:"订单"跨五类资产一次召回
背景
分析师老王被问到"订单相关的资产都在哪?"以前要对象查询、指标管理、数据集页一个个翻。现在 Foundry 顶栏有一个全局搜索框,他输入"订单",一个回车——对象、指标、数据集、仪表盘、Notebook 五类资产并行召回、融合排序后一起出现在下拉里。
传统做法对比
以前找资产靠记忆和收藏,忘了路径就在各模块里来回翻;跨类型对比口径更无从下手。现在五 scope 并行检索(objects 走语义检索含对象级可见性、metrics 走目录 LIKE、datasets/dashboards/notebooks 按 scope 查表),RRF 融合统一排序,点击即跳转对应功能页。
角色
业务分析师(搜索 + 跳转);对象级可见性由语义检索的 AuthorizeObjectFunc 把关。
操作步骤
  1. 在 Foundry 顶栏输入"订单"(输入后 300ms 防抖自动请求)
  2. 下拉出现对象 / 数据集 / 工作簿等命中(类型徽标 + 标题 + 摘要)
  3. 点击"订单对象"跳转 /foundry/query?name=order
  4. 再输入"gmv"按 Enter 跳首个结果(指标页)
系统响应
GET /api/v1/nexus/search?q=订单 返回融合结果:
{ "code": 0, "data": { "hits": [
  { "uri": "dataset://foundry/ds-1", "title": "订单数据集",
    "snippet": "订单明细行数据集", "type": "datasets", "score": 0.016 },
  { "uri": "metric://foundry/total_gmv", "title": "总销售额",
    "snippet": "订单总金额口径", "type": "metrics", "score": 0.016 },
  { "uri": "object://foundry/order", "title": "订单",
    "snippet": "订单对象", "type": "objects", "score": 0.016 } ],
  "total": 3 } }
结果洞察
五 scope 在 goroutine 中并行执行,整体时延 ≈ 最慢 scope;RRF 融合分 = Σ 1/(60+rank+1),同分按 type/title 字典序确定输出(datasets < metrics < objects);统一 URI(object://foundry/<apiName>、metric://foundry/<name>、dataset://foundry/<rid> 等)是融合去重与前端路由映射的锚点;无读权限的对象不会出现在结果(admin 通配)。
调整建议
想只搜指标就传 scopes=metrics;前端跳转后目标页目前不会自动选中路由参数,可手动再过滤一次;搜索量大时优先给目录类表加 name/description 索引。
动手试一试
登录:admin / admin1。页面路径:Foundry 顶栏。输入内容:输入"订单",再输入"gmv"回车。预期结果:下拉出现对象 / 数据集等命中;点击对象跳转 /foundry/query?name=order;"gmv"回车跳转指标页。
限制提示
跳转仅定位功能页,目标页暂无路由参数自动选中能力;docs scope 未注入返回空;无向量索引,极端口语化描述命中率有限。
故事 2 容错与热度:单 scope 故障不阻断,fx_search_stats 记热搜
背景
运维想验证两件事:搜索接口在某个 scope 后端故障时会不会整体挂掉;以及"本周热搜词"从哪统计。他先试了空查询与超大 limit,再注入一个会报错的 scope,最后查 fx_search_stats 表看热度记录。
传统做法对比
以前聚合检索要么没做,要么一挂全挂、还无热度记录。现在单 scope 容错:scope 检索失败只记 Warn 日志跳过,其余 scope 照常返回;只有全部 scope 均失败才向调用方返回 500。热度统计 best-effort:每次成功搜索落一条 fx_search_stats(q + 融合去重后命中数),写失败仅 Warn 不阻断主流程。
角色
平台管理员 / 运维(验证容错 + 统计热搜)。
操作步骤
  1. GET /nexus/search?q=(空)观察 422
  2. GET /nexus/search?q=订单&limit=100 观察钳制
  3. 构造单 scope 故障场景(注入错误 searcher)观察降级
  4. 查询 fx_search_stats 表统计热搜词
系统响应
q 为空返回 422:
{ "code": "VALIDATION_ERROR", "error": "查询词 q 不能为空" }
单 scope 故障时其余 scope 照常:
{ "code": 0, "data": { "hits": [
  { "uri": "metric://foundry/total_gmv", "title": "总销售额",
    "snippet": "订单总金额口径", "type": "metrics", "score": 0.016 } ],
  "total": 1 } }
热度表落一条:
{ "q": "订单", "hit_count": 3, "created_at": "2026-08-30T10:00:00Z" }
结果洞察
limit 钳制发生在服务层(默认 20、上限 50),searcher 收到的 limit 已钳制;scopes 去重保序、未知 scope 忽略、全非法回退默认五 scope;热度表 hit_count 记录的是融合去重后的命中数(len(fused)),不是各 scope 命中之和,统计口径要先清楚。
调整建议
热度表无 retention job,建议定期清理或后续实现归档;"热门搜索"按 q 聚合即可;想深究搜索质量可关注"单条搜索各 scope 命中"——目前热度表只记总数不记分 scope 明细。
动手试一试
登录:admin / admin1。输入内容:GET /nexus/search?q=(空);GET /nexus/search?q=订单&limit=100。预期结果:空 q 返回 422;limit=100 实际返回 ≤50 条;每次成功搜索 fx_search_stats 新增一行。
限制提示
热度表只增不清理,高并发下会累积;无向量索引、目录 LIKE 朴素匹配;跳转不自动选中目标页参数。
故事 3 actionctl 命令行:登录、导本体、查指标、探活 MCP 一条龙
背景
数据工程师小唐不想为"导一份对象 YAML、看一眼数据集、查个指标"开浏览器。他用 actionctl 命令行完成一套日常操作:login 存凭据、ont export 导出 order 进 Git、metric query 查总销售额、mcp ping 探活 MCP 是否启用。
传统做法对比
以前命令行要么没有,要么是内部脚本与后端强耦合,环境变量、token、输出格式各搞一套。actionctl 是纯 HTTP client(flag 包,不引 cobra、不引 products 包),配置三源优先级(flag > ACTIONCTL_BASE / ACTIONCTL_TOKEN > ~/.actionctl > 默认),输出 JSON + --format table 双格式,单测不发网络。
角色
数据工程师 / 运维(命令行操作);AI 编码 agent 也可用同一 CLI 做纯 HTTP 交互。
操作步骤
  1. actionctl login --base URL --username admin --password ...(成功后 token 写入 ~/.actionctl,0600)
  2. actionctl ont export order --format yaml -o order.yaml(进 Git 评审)
  3. actionctl metric query total_gmv --dims region --format table
  4. actionctl mcp ping(404 即 MCP 未启用,退出码 1)
系统响应
登录成功写入凭据:
{ "ok": true, "base": "http://localhost:18081",
  "username": "admin", "token": "<JWT>", "token_type": "bearer",
  "stored_to": "C:\\Users\\pan\\.actionctl" }
指标查询 table 输出:
  region   total
  cn       12800.5
  us       9500.0
MCP 探活(启用时):
{"jsonrpc":"2.0","id":1,"result":{"tools":[{...5 个工具...}]}}
结果洞察
7 个子命令覆盖运维场景:login / ont export(yaml|json|owl|shacl,-o 落盘)/ ont import / dataset list|get|preview / task list|get|cancel(挂 /system/tasks 前缀)/ metric query / mcp ping。token 存储 0600 仅本人可读;--format table 自动剥离 {code:0,data} 包装让表格紧凑;MCP 未启用返回 404 + 退出码 1,脚本可判活。
调整建议
CI / 脚本场景用 ACTIONCTL_TOKEN 环境变量注入,避免明文落盘;ont export --format owl|shacl 可对接外部语义工具;dataset preview --limit 传大值由服务端钳制(上限 500),不会拉爆内存。
动手试一试
环境:action/ 目录下 go build -o actionctl ./cmd/actionctl。输入内容:actionctl login 后执行 actionctl dataset list --format table、actionctl metric query total_gmv --dims region。预期结果:数据集 / 指标查询以表格输出;actionctl mcp ping 在未启用 MCP 时返回错误与退出码 1。
限制提示
metric query 的 --filters 只生成 op=eq 条件;配置为单 profile(~/.actionctl 只有一套 base/token);交互式建模 / Action 设计仍在 Web 端;任务命令走 /system/tasks 前缀,与协作工作流 /tasks/:taskId 区分。

常见问题

Nexus 和前端"语义检索"页有什么区别?

语义检索页调 POST /ontology/semantic-search,返回结构化 metric/object/property 三类命中(含 payload),面向"深度语义检索";Nexus 是顶栏聚合入口,五 scope 并行 + RRF 融合 + 统一 URI,只展示标题 / 摘要 / 类型并跳转功能页。两者共享同一 semantic 检索服务,scope 集合与输出形态不同。

同 URI 跨 scope 累加会不会把同一资源重复计权?

会——这正是 RRF 的设计意图:同一资源在越多类型下被召回,说明它与查询词相关度越高,融合分累加使其排位更靠前。去重后每条 URI 只出现一次。例:某数据集被工作簿引用,datasets 与 notebooks 都命中它,融合分 1/61+1/61≈0.033 置顶。

docs scope 为什么返回空?

Deps.Docs = nil——跨产品联 AIP 知识库需要 AIP 侧检索适配,P0 只做 foundry 域。显式请求 scopes=docs 时该 scope 空、其余照常,不报错;这是"能力未注入"的显式语义,不是故障。

actionctl 的 token 存在哪里、安全吗?

~/.actionctl(Windows 为 %USERPROFILE%\.actionctl),0600 权限仅本人可读,内容为 {base, token} JSON。CI / 脚本场景建议用 ACTIONCTL_TOKEN 环境变量注入,避免明文落盘。配置优先级:flag > 环境变量 > 存储文件 > 默认。

actionctl mcp ping 返回 404 算成功吗?

不算。404 是"MCP 未启用"(foundry.mcp.enabled=false 或路由未挂载)的明确信号:actionctl 输出 JSON-RPC error 形态结果并返回错误、退出码 1——脚本可据此判活。启用后则返回 tools/list 的 JSON-RPC 响应。

主题小结

一句话:Nexus 让"找得到"(顶栏一框、五 scope 并行、RRF 融合、统一 URI 跳转、热度可统计),actionctl 让"用得了"(7 子命令、纯 HTTP、双输出格式、可进 CI)。记住几个边界:docs scope 未注入、无向量索引、跳转不自动选中、--filters 仅 eq、热度表无 retention。