Elasticsearch7如何通过Java API直接执行Kibana原生JSON查询?
核心实现方案
你需要的API原生存在,无需引入额外依赖,直接通过RestHighLevelClient即可实现,示例代码如下:
import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.common.xcontent.XContentType; // 初始化RestHighLevelClient(通用初始化逻辑和原有方案一致) RestHighLevelClient client = initEsClient(); String indexName = "telemetry"; // query为模板引擎生成的完整查询JSON字符串 String query = engine.compile(json_resource).execute(Map.of("interval_param", 50)); SearchRequest searchRequest = new SearchRequest(indexName); // 直接传入JSON字符串作为查询条件 searchRequest.source(query, XContentType.JSON); SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); // 后续解析response的逻辑和原有Java API方案完全一致
方案优缺点
优点
- 开发效率提升显著:完全省去Kibana调试完成后JSON转Java构造器的步骤,没有语法转换成本,复杂聚合、多条件查询场景下收益尤其突出
- 查询逻辑易于统一管理:所有查询规则都放在资源目录的JSON文件中,不需要散落在Java业务代码里,调整查询规则不需要修改Java代码,仅调整JSON模板即可
- 降低学习成本:不需要记忆各类ES Java API的构造器用法,仅需掌握ES原生JSON查询语法即可完成开发
缺点
- 无编译期校验:Java API构造的查询部分语法问题可以在编译阶段发现,JSON模板的语法错误、字段错误等问题只能在运行时执行查询时才能暴露
- 复杂参数替换易出错:如果参数是字符串、数组等类型,简单的模板替换容易出现JSON格式错误,比如字符串未加引号、数组格式不合法等
- 缺乏语法提示:JSON模板在IDE中默认没有ES语法的自动补全、错误提示能力,超复杂查询的模板维护成本会高于Java API方案
性能对比
该方案和原生Java API构造查询的性能几乎没有差异。Java API构造查询的底层逻辑,也是将构造好的查询对象序列化为JSON字符串再发送给ES服务端,直接传递JSON字符串相当于跳过了Java对象序列化的步骤,理论上性能甚至略高于原生Java API方案,不存在额外性能损耗。
安全风险说明
该方案确实存在类似SQL注入的风险,但可以通过规范操作完全规避:
- 如果参数完全由后端生成,不接收前端传入的自定义内容,不存在任何注入风险
- 如果参数接收前端传入,直接拼接用户输入会有风险:比如用户输入携带
"、}等特殊字符,会破坏JSON结构,甚至被恶意构造出越权查询、全表扫描的请求 - 规避方案:数值类型参数必须先做类型和范围校验再填入模板;字符串类型参数要先做JSON转义再填充;也可以使用ES原生的搜索模板功能,将参数和查询逻辑分离,由ES服务端负责参数的安全填充,彻底规避注入风险
内容的提问来源于stack exchange,提问作者Mark Bramnik
相关产品推荐
相关产品推荐

