如何在Elasticsearch Java Client 8的msearch请求中使用script_fields
Elasticsearch Java Client 8 实现多搜索(Multi Search)请求
要实现你提供的多搜索请求,核心是为每个单独的SearchRequest配置查询条件和脚本字段,再将这些请求组装到MultiSearchRequest中执行。以下是具体代码实现:
1. 构建查询条件和脚本字段
首先,针对每个搜索请求,构建地理距离过滤、布尔查询,以及计算距离的脚本字段:
// 定义目标坐标(用于geo_distance过滤) double targetLat = 12.9322; double targetLon = 77.6904; // 定义脚本字段中用于计算距离的坐标 double scriptLat = 40.00327; double scriptLon = 15.36496; // 构建地理距离过滤条件 GeoDistanceQuery geoDistanceQuery = GeoDistanceQuery.of(g -> g .field("latLon") .distance("3km") .distanceType(GeoDistanceType.Arc) .location(l -> l.lat(targetLat).lon(targetLon)) ); // 构建布尔查询 BoolQuery boolQuery = BoolQuery.of(b -> b .must(m -> m.matchAll(m2 -> m2)) .filter(f -> f.geoDistance(geoDistanceQuery)) ); // 构建脚本字段(参数化写法避免注入风险) ScriptField distanceScriptField = ScriptField.of(s -> s .script(sc -> sc.inline(i -> i .source("doc['latLon'].arcDistance(params.lat, params.lon)") .params("lat", scriptLat) .params("lon", scriptLon) )) );
2. 组装单个搜索请求
将上述查询和脚本字段绑定到SearchRequest,每个请求可独立配置:
// 第一个搜索请求 SearchRequest searchRequest1 = SearchRequest.of(s -> s .index("your-index-name") // 替换为你的索引名 .query(q -> q.bool(boolQuery)) .scriptFields(fields -> fields.put("distance_in_m", distanceScriptField)) ); // 第二个搜索请求(逻辑与第一个一致,可复用查询和脚本字段) SearchRequest searchRequest2 = SearchRequest.of(s -> s .index("your-index-name") // 替换为你的索引名 .query(q -> q.bool(boolQuery)) .scriptFields(fields -> fields.put("distance_in_m", distanceScriptField)) );
3. 组装并执行多搜索请求
将多个SearchRequest添加到MultiSearchRequest,通过客户端执行并处理结果:
// 初始化Elasticsearch客户端(需提前完成配置) ElasticsearchClient client = new ElasticsearchClient(/* 你的客户端配置 */); // 构建多搜索请求 MultiSearchRequest multiSearchRequest = MultiSearchRequest.of(m -> m .operations(op -> op.search(searchRequest1)) .operations(op -> op.search(searchRequest2)) ); // 执行请求 MultiSearchResponse response = client.msearch(multiSearchRequest); // 遍历处理响应结果 for (MultiSearchResponse.Item item : response.items()) { if (item.isFailure()) { System.out.println("请求失败: " + item.failure().reason()); continue; } SearchResult result = item.result(); for (Hit<Object> hit : result.hits().hits()) { Object distance = hit.fields().get("distance_in_m").value(); System.out.println("文档ID: " + hit.id() + ",计算距离: " + distance + "米"); } }
关键说明
- 每个
SearchRequest通过scriptFields(fields -> fields.put(...))方法独立配置脚本字段,这就是8.x版本中为单个查询添加脚本字段的方式。 - 脚本采用参数化写法而非直接拼接字符串,能有效避免脚本注入风险,适合动态传入坐标的场景。
内容的提问来源于stack exchange,提问作者maulik trapasiya
相关产品推荐
相关产品推荐

