如何使用RestHighLevelClient将自定义JSON查询转为Elasticsearch的SearchRequest
RestHighLevelClient直接传入JSON查询串的标准实现方案
方案1:直接解析完整查询JSON(推荐,无需手动剥外层query)
这是最适配你场景的方案,前端传入的本身就是符合ES Search API请求体结构的JSON,直接解析为SearchSourceBuilder即可,不需要用到WrapperQuery,也无需修改前端传入的JSON结构:
import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.search.builder.SearchSourceBuilder; import java.io.IOException; // 前端传入的完整查询JSON String frontQueryJson = "{\"query\":{\"term\":{\"something.keyword\":\"something\"}}}"; // 构建SearchRequest,指定要查询的索引名 SearchRequest searchRequest = new SearchRequest("your_index_name"); // 直接把完整JSON解析为SearchSourceBuilder,支持query、from、size、sort、aggs等所有ES查询原生参数 SearchSourceBuilder sourceBuilder = SearchSourceBuilder.fromXContent( XContentParser.builder(XContentType.JSON.xContent()) .build(frontQueryJson) ); searchRequest.source(sourceBuilder); // 执行查询 // restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
方案2:保留WrapperQuery的实现(需要手动剥离外层query)
如果你一定要用WrapperQueryBuilder的方式实现,就需要先把前端传入JSON的外层query节点内容提取出来,再传入WrapperQuery:
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.elasticsearch.index.query.WrapperQueryBuilder; import org.elasticsearch.search.builder.SearchSourceBuilder; ObjectMapper objectMapper = new ObjectMapper(); String frontQueryJson = "{\"query\":{\"term\":{\"something.keyword\":\"something\"}}}"; // 提取query节点的内容字符串 JsonNode rootNode = objectMapper.readTree(frontQueryJson); String queryPartJson = objectMapper.writeValueAsString(rootNode.get("query")); // 构建WrapperQuery WrapperQueryBuilder wrapperQuery = new WrapperQueryBuilder(queryPartJson); SearchSourceBuilder sourceBuilder = new SearchSourceBuilder().query(wrapperQuery); // 后续组装SearchRequest逻辑同方案1
注意事项
- 两种方案都默认前端传入的JSON符合ES查询语法,生产环境建议增加语法合法性校验、权限校验,避免恶意查询拖库、或语法错误导致服务异常。
- 如果你使用的是7.x以下的旧版本ES,
fromXContent方法的调用方式可能有细微差异,对应调整API参数即可。
内容的提问来源于stack exchange,提问作者Pikappa
相关产品推荐
相关产品推荐

