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

Spring Elasticsearch:如何基于main_id而非id批量Upsert文档

基于main_id实现Elasticsearch批量Upsert的改造方案

需求背景

原本我们通过Elasticsearch文档自带的id字段实现批量Upsert(不存在则插入,存在则更新),现在需求变更为:文档id由Elasticsearch自动生成,新增main_id作为业务主键,需要基于main_id来实现批量Upsert逻辑。

实体类调整

首先要确保main_id字段能被精确匹配,给它添加Keyword类型的映射(避免分词导致匹配失败):

@Data
@Document(indexName = "person")
public class Person {

  @Id
  @JsonIgnore
  private String id;

  @Field(type = FieldType.Keyword) // 标记为精确匹配的关键词类型
  private String mainId;

  private String name;
}

批量Upsert方法改造

原来的方法是基于文档id构建更新请求,现在需要改为通过main_id字段匹配目标文档,修改后的代码如下:

public void bulkCreateOrUpdate(final List<T> objectList) {
    List<UpdateQuery> updateList = new ArrayList<>();
    ElasticsearchConverter converter = this.operations.getElasticsearchConverter();

    for (T st : objectList) {
        // 构建匹配main_id的查询条件,确保找到对应业务主键的文档
        Query query = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.termQuery("mainId", st.getMainId()))
                .build();

        UpdateQuery updateQuery = UpdateQuery.builder(query)
                .withDocument(converter.mapObject(st))
                .withDocAsUpsert(true) // 开启Upsert逻辑:无匹配则插入新文档
                .withGenerateId(true) // 插入时自动生成Elasticsearch文档id
                .build();
        updateList.add(updateQuery);
    }

    this.operations.bulkUpdate(updateList, this.operations.getIndexCoordinatesFor(this.entityClass));
}

关键说明

  • 替换更新依据:不再依赖文档id,而是通过termQuery精确匹配main_id字段定位目标文档
  • 自动生成文档id:通过withGenerateId(true)让Elasticsearch在插入新文档时自动生成唯一的id值,符合需求变更
  • 唯一约束建议:为了避免main_id重复,建议在Elasticsearch索引的mapping中给main_id添加唯一约束(设置"unique": true),从存储层面保证业务主键的唯一性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 15:25:15