You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot结合Spring Data Elasticsearch如何返回距离与全部字段

Spring Data Elasticsearch 实现带script_fields的ES查询方案

完整实现代码

import org.springframework.data.elasticsearch.core.query.ScriptField;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
import org.springframework.data.domain.PageRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import static org.elasticsearch.index.query.QueryBuilders.*;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.script.Script;

// 1. 构造原生查询对应的Bool查询条件
BoolQueryBuilder boolQueryBuilder = boolQuery()
        .should(constantScoreQuery(termQuery("my_field", "my_value")).boost(10))
        .should(constantScoreQuery(termQuery("my_field", "my_value")).boost(8))
        .filter(termsQuery("my_array_field", "first_value", "second_value"))
        .filter(geoDistanceQuery("location")
                .distance("10km")
                .lat(40)
                .lon(2)
        );

// 2. 构造距离计算的脚本字段
Script distanceScript = new Script("doc['location'].arcDistance(40, 2) / 1000");
ScriptField distanceScriptField = new ScriptField("distance", distanceScript);

// 3. 构造完整查询对象
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                .withPageable(PageRequest.of(page, size))
                // 注入脚本字段
                .withScriptField(distanceScriptField)
                // 显式配置返回全部_source字段
                .withSourceFilter(new FetchSourceFilter(true, null))
                // 按得分降序排序
                .withSort(SortBuilders.scoreSort().order(SortOrder.DESC))
                .build();

// 4. 执行查询并获取返回的距离值
SearchHits<MyIndexedDocument> searchHits = elasticsearchOperations.search(nativeSearchQuery, MyIndexedDocument.class);
// 遍历结果获取每条记录的距离
for (SearchHit<MyIndexedDocument> hit : searchHits) {
    Double distance = (Double) hit.getFields().get("distance").getValue();
    // 后续可将距离赋值给实体类或做业务处理
}

疑问解答

1. ScriptField的正确使用方式

  • 先构造org.elasticsearch.script.Script对象,传入你需要执行的Painless脚本内容
  • 再构造org.springframework.data.elasticsearch.core.query.ScriptField对象,第一个参数为返回的脚本字段名,第二个参数为上述构造的Script对象
  • 调用NativeSearchQueryBuilder的withScriptField方法传入构造好的ScriptField即可
  • 查询执行完成后,从SearchHit的getFields()方法中即可取到对应名称的脚本字段值

2. 配置返回全部_source字段的方法

可以直接通过NativeSearchQuery完成配置,只需要在构造查询时调用withSourceFilter方法,传入new FetchSourceFilter(true, null)即可:

  • 第一个参数true表示返回_source字段
  • 第二个参数传null表示不做字段过滤,返回全部_source字段
    如果后续需要指定返回部分字段,修改第二个参数为需要保留的字段名数组即可。

内容的提问来源于stack exchange,提问作者Maaz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 12:30:02