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

如何在Spring Boot中通过RestHighLevelClient递归向Elasticsearch嵌套文档插入数据

Spring Boot 基于RestHighLevelClient向nested嵌套字段追加数据实现方案

前置说明

你当前的索引中companyaddress是nested嵌套类型,要实现追加数据无需每次全量查询再覆盖,直接用Elasticsearch的painless脚本更新即可,性能更高且避免并发冲突。

第一步:引入依赖(确认版本匹配)

确保你的pom.xml引入对应版本的ES客户端依赖,版本需和你部署的ES集群大版本完全一致:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    <!-- 版本和Spring Boot版本对应,确保ES客户端版本和集群版本一致 -->
</dependency>

第二步:定义对应实体类

import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import java.util.List;

@Document(indexName = "你的实际索引名")
public class Company {
    @Field(type = FieldType.Long)
    private Long companyId;

    @Field(type = FieldType.Text, analyzer = "likely_analyzer", searchAnalyzer = "standard")
    private String companyName;

    @Field(type = FieldType.Nested)
    private List<CompanyAddress> companyaddress;

    // 省略getter、setter方法
}

class CompanyAddress {
    @Field(type = FieldType.Text, analyzer = "likely_analyzer", searchAnalyzer = "standard")
    private String address3;

    @Field(type = FieldType.Long)
    private Long mainPhone1;

    // 省略getter、setter方法
}

第三步:核心追加数据实现(推荐脚本更新方式)

直接通过更新请求+脚本实现原子追加,无需先查询文档:

import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.HashMap;
import java.util.Map;

@Service
public class CompanyEsService {
    @Autowired
    private RestHighLevelClient restHighLevelClient;
    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 向companyaddress字段追加新地址
     * @param docId 目标文档ID
     * @param newAddress 待新增的地址对象
     */
    public void appendCompanyAddress(String docId, CompanyAddress newAddress) throws Exception {
        UpdateRequest updateRequest = new UpdateRequest("你的实际索引名", docId);
        // 构造painless执行脚本
        Map<String, Object> params = new HashMap<>();
        params.put("newAddress", objectMapper.convertValue(newAddress, Map.class));
        Script script = new Script(ScriptType.INLINE, "painless",
                "if (ctx._source.companyaddress == null) {ctx._source.companyaddress = new ArrayList();} ctx._source.companyaddress.add(params.newAddress)",
                params);
        updateRequest.script(script);
        // 开启冲突重试,最多重试3次解决并发更新问题
        updateRequest.retryOnConflict(3);
        // 执行更新请求
        UpdateResponse response = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
    }
}

注意事项

  • 如果是新增文档,直接给companyaddress赋值为包含首个元素的List即可,无需走追加逻辑
  • 确保RestHighLevelClient的版本和ES服务端大版本一致,否则会出现兼容性问题
  • 如果需要插入数据后立即查询可见,可以给updateRequest设置setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE),但会牺牲写入性能,非必要不开启

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 01:00:03