一个开源的 Elasticsearch 查询与运维控制台。同一套 Vue 源码,既能作为 Spring Boot starter 嵌入宿主,也能打包成 Chrome MV3 扩展直连 ES。在线演示:dengmeiluan.github.io/esquerystud...
为什么要再做一个 ES 控制台
大部分 Elasticsearch 控制台把「查询」拆成了互不相通的工具页:DSL 构建器一页、SQL 一页、Explain 一页,写完条件树还要手抄 JSON;补全只给关键字,不管字段是 text 还是 keyword,也不管分词器和集群版本;分数不对只能猜,慢查询只能翻日志。
对 Spring Boot 团队还有一层麻烦:为了一个查询台,要再部署一套 Kibana,登录态、菜单、权限和审计都接不回宿主应用。
ESQueryStudio 想解决的就是这条链路:把「怎么写、怎么跑、为什么命中、为什么慢」收进一个连续的查询现场,同时让控制台可以作为 Spring Boot 应用的一部分交付。
六种模式,共用一个现场
控制台不是六个互相跳转的工具页,而是同一份查询现场换视图:
- DSL 构建器 + 原始编辑器:条件树和 JSON 双向同步;不认识的子句退回原文编辑,不静默丢结构。
- ES-SQL :支持
_sql查询、cursor 深分页、字段体检,结果可在表格 / JSON / Tree / 卡片之间切换,并能转成 DSL 继续精修。 - Lucene:保留原始高亮与命中行,可带去构建器继续改。
- 查询沙盒 :自由写 DSL、看原始响应、对比
_source与高亮,适合验证一个假设。 - PIT 深分页:基于 Point-in-Time 的稳定翻页,游标断了能解释、能续拉,不在 10k 窗口前停住。
- SQL ⇄ DSL 语法桥:翻译时保留语义差异提示,不把「翻译成功」当成「语义等价」。
切换模式、翻页、刷新都不会把写到一半的查询清空;历史、收藏、草稿和分享深链共用同一套现场。
真正懂 ES 的语义层
补全和 lint 不应该只认识关键字。ESQueryStudio 的语义层会读取当前索引的实时信息:
- 字段类型、
text/keyword子字段、nested 结构; - 分词器、normalizer、同义词与
analysis设置; - 可排序性、日期格式、字段角色;
- 当前集群版本对应的能力边界。
这些信息一起参与补全、值枚举、执行前检查和语义 lint。例如:在 text 字段上直接排序会提醒走 .keyword;字段不存在、类型不可排序、日期格式不匹配、聚合与排序冲突,都会在执行前给出可操作的修复建议。
条件树改完,JSON 立即更新;JSON 改完,条件树按语义重建。只改一边、另一边静默过期的情况不会发生。
相关性实验室:从「为什么命中」到「为什么慢」
查询工作台和相关性实验室共享同一个查询现场:
- 打分解剖 :把每个命中文档的 BM25 因子树展开到
tf/idf/boost/norm; - 排名侦探:对单个文档追问「为什么是它」,对比不同查询下的得分路径;
- 查询 X 光:逐子句查看词项、命中数和分析器改写后的实际查询;
- 子句命中矩阵:哪条子句命中了哪些文档,一屏对齐,专门抓「写了但没起作用」的条件;
- Boost 调参沙盒:边改权重边看排名变化;
- Profile 火焰图 :把
profile=true的查询 / 采集器耗时展开,定位慢在 rewrite、build_scorer 还是 next_doc。
一套 Vue 源码,两种发布形态
这是项目里最想分享的架构选择:控制台只有一套 Vue 3 源码,服务端模式和浏览器模式只切换最底层的 transport。
text
ui/ (Vue 3, 52 pages)
├─ server mode → /internal/es/index → Spring Boot console
└─ browser mode → browserApi.ts → Elasticsearch REST directly
服务端模式 :Spring Boot 提供 /internal/es/index 适配层,控制台随应用发布,共享宿主登录态、路由、菜单与页面级权限。交付形态支持独立 jar、嵌入式 console 模块、宿主 SPI 和 rebuild-only 引擎。
浏览器模式 :Chrome MV3 扩展内运行同一套源码的 browser 构建,直连 Elasticsearch,不需要后端。首次连接填写 ES 地址和认证,支持多个本机连接档案与顶栏切换;监控、审计、重建 / 迁移作业都落在本机 IndexedDB / localStorage。
这里最重要的不是「把 UI 搬进插件」,而是能力覆盖要有边界且诚实:
- 浏览器模式没有跨实例分布式锁和代码 provider,系统页展示本机作业锁,配置漂移以本机首次基线为准;
- 关闭标签页后,service worker 仍按分钟为每条连接写集群 / 每节点 / Top 索引行,并继续做阈值告警;
- 受限账号缺少
_nodes/_cat/_stats权限时,只硬依赖_cluster/health,节点 / 索引明细降级为空,不制造假 RED; - 客户端跨集群迁移在关闭标签页后会标记
INTERRUPTED,需要显式恢复。
为了不让「只实现服务端、忘了纯前端」再次发生,仓库里加了 scripts/check-browser-parity.mjs:同时扫描 api.ts、后端 Controller 映射和页面契约前缀,新增端点没有浏览器实现就直接让 CI 失败;确实无法实现的少数端点必须登记原因,并在 UI 显示真实边界。
工程化与质量
- 52 页、13 分组、11 个功能包;页面契约
META-INF/esquerystudio-pages.json是前端导航、后端页面门和宿主菜单注册器的唯一事实源。 - 页面级授权按「连接 × 页面 × 读 / 写」执法,不用隐藏菜单冒充权限。
- 前后端全量测试:前端 1,519 文件 / 12,209 例,后端覆盖认证、页面授权、重建状态机、映射对账、跨集群迁移与存储档。
- 真实浏览器探针、权限矩阵、可复现构建、SBOM、CodeQL、OpenSSF Scorecard、Dependabot 一起上。
ConsoleHostIntegration、ConsoleAuthDelegate、ConnStore、ConsoleAuditContributor四个 SPI 分别接管品牌、认证、连接目录和审计,不把宿主业务字段硬编码进平台。
几张真实控制台截图
查询工作台:条件树、原始 DSL、结果和直方图在同一屏。

打分解剖:每个命中文档的 BM25 因子树。

Chrome 扩展:同一套 52 页 Vue 控制台在扩展内直连 ES。

5 分钟体验
独立部署:
bash
java -jar esquerystudio-server-1.0.0.jar
# 打开 http://localhost:5601/esquerystudio.html
嵌入 Spring Boot:
xml
<dependency>
<groupId>io.github.dengmeiluan</groupId>
<artifactId>esquerystudio-console</artifactId>
<version>1.0.0</version>
</dependency>
ES 客户端栈由宿主以 provided 契约自备;启动时会比对真实类型签名,不匹配直接拒绝启动并给出修复路径。
- 在线演示(合成数据,点开即玩):dengmeiluan.github.io/esquerystud...
- GitHub:github.com/dengmeiluan...
- 文档:github.com/dengmeiluan...
适合谁
- 用 Spring Boot / Java 把 Elasticsearch 作为主搜索或日志存储,希望控制台跟应用一起发布;
- 搜索质量 / 相关性团队,需要把打分、命中矩阵、Profile 放在同一个现场;
- 平台团队要交付「可查、可改、可治理」的 ES 能力,需要页面级权限、连接目录和审计 SPI;
- 正在做索引重建、跨集群迁移或容量治理的团队。
最后
项目使用 Apache-2.0 开源,当前是初始版本滚动更新。如果你正在做 Elasticsearch 查询、相关性调优或 Spring Boot 控制台集成,欢迎试用、提 issue 或直接交流使用场景。