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
相关产品推荐
相关产品推荐

