如何通过MongoRepository单次IO批量更新MongoDB多条数据
MongoRepository实现单IO批量更新配置激活状态方案
首先明确:MongoRepository默认提供的基础方法不支持类似MySQL的跨文档条件式单语句更新,你可以通过Spring Data MongoDB封装的MongoTemplate配合对应API实现单次IO完成所有配置的active字段更新,完全替代你之前findAll+saveAll的低效率实现。
方案1:兼容所有MongoDB版本的批量操作方案
该方案基于MongoDB的批量写能力实现,所有更新指令会打包成单次请求发送给服务端,仅产生一次网络IO,无版本兼容问题:
import org.springframework.data.mongodb.core.BulkOperations; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.Date; @Service public class ConfigService { @Resource private MongoTemplate mongoTemplate; public void activateConfig(String targetConfigId) { // 初始化无序批量操作,互斥条件下无序模式执行效率更高 BulkOperations bulkOps = mongoTemplate.bulkOps( BulkOperations.BulkMode.UNORDERED, Config.class ); // 将所有非目标ID的配置active置为false Query falseQuery = new Query(Criteria.where("id").ne(targetConfigId)); Update falseUpdate = new Update().set("active", false); bulkOps.updateMulti(falseQuery, falseUpdate); // 将目标ID配置active置为true,同时更新修改时间 Query trueQuery = new Query(Criteria.where("id").is(targetConfigId)); Update trueUpdate = new Update().set("active", true).set("updateDate", new Date()); bulkOps.updateOne(trueQuery, trueUpdate); // 执行批量操作,单次请求完成所有更新 bulkOps.execute(); } }
方案2:MongoDB 4.2+ 单语句更新方案
MongoDB 4.2及以上版本支持在更新操作中使用聚合表达式,逻辑和你写的MySQL更新语句完全等价,单条指令即可完成全表更新,代码更简洁:
public void activateConfigSingle(String targetConfigId) { // 空查询条件匹配集合内所有文档 Query allQuery = new Query(); // 直接通过表达式判断_id是否等于目标ID,设置对应active值 Update aggUpdate = new Update() .set("active", new org.bson.Document("$eq", java.util.List.of("$_id", targetConfigId) )) .set("updateDate", new Date()); mongoTemplate.updateMulti(allQuery, aggUpdate, Config.class); }
注意:如果你的Config集合
_id字段在MongoDB中存储为ObjectId类型,需要把targetConfigId转为new ObjectId(targetConfigId)再传入表达式,否则会因为类型不匹配导致判断失效。
如果需要把这类逻辑封装到Repository层,只需要自定义Repository实现类,把上述MongoTemplate操作封装为自定义方法即可,不需要在业务层直接依赖MongoTemplate。
内容的提问来源于stack exchange,提问作者kuoyuan
相关产品推荐
相关产品推荐

