Spring Boot MongoTemplate嵌套数组元素移除失败问题排查
问题:Spring Boot MongoTemplate无法从嵌套数组移除指定值
我尝试用Spring Boot的MongoTemplate自定义更新操作,从嵌套数组里移除指定值。
示例文档
{ "email": "xxxxxxxxxxxxxxxxx@demo.com", "t_maps": [ { "app_name": "2321321", "app_id": [ "E-123456789", "A-123456789" ] }, { "app_name": "23231", "app_id": [ "E-123456789", "A-123456789" ] }, { "app_name": "abcd 121", "app_id": [ "E-123456789", "A-123456789" ] } ] }
Mongo Shell中可成功执行的命令
db.user_maps_id.update( {email: {"$in": ["yyyyyyyyyyyyyyyyy@demo.com","xxxxxxxxxxxxxxxxx@demo.com"]}}, {$pull: {"t_maps.$[].app_id": "A-123456789"}}, {multi: true} )
代码问题
在Java代码中执行时,匹配计数为2,但修改计数为0,无法移除子数组中的值。相关代码如下:
自定义Repository
public interface CustomUserMapsIdRepository { void updateUserMapsIdRepository(List<CustomUserMapsId> userMapsIdRepository, String app_id); }
实现类
@Component public class CustomUserMapsIdRepositoryImpl implements CustomUserMapsIdRepository { @Autowired MongoTemplate mongoTemplate; @Override public void updateUserMapsIdRepository(List<CustomUserMapsId> userMapsIdRepository, String app_id) { List<String> emails = userMapsIdRepository.parallelStream().map(i -> i.getEmail()).collect(Collectors.toList()); Query query = new Query(Criteria.where("email").in(emails)); Update update = new Update(); update.pull("t_maps.$[].app_id", app_id); UpdateResult result = mongoTemplate.updateMulti(query, update, UserToolEngagements.class); BulkWriteResult execute = mongoTemplate.bulkOps(BulkOperations.BulkMode.ORDERED, UserToolEngagements.class) .updateMulti(query, update) .execute(); int matchedCount = execute.getMatchedCount(); System.out.println("matchedCount = " + matchedCount); int modifiedCount = execute.getModifiedCount(); System.out.println("modifiedCount = " + modifiedCount); } }
排查与解决方案
移除重复更新操作:代码中连续执行了
mongoTemplate.updateMulti和bulkOps.updateMulti两次更新。第一次更新已经完成数据修改,第二次执行时无数据可改,导致修改计数为0。保留其中一种更新方式即可。验证版本兼容性:
$[](全位置操作符)是MongoDB 3.6+引入的特性,对应的Spring Data MongoDB版本需为2.0及以上。如果版本过低,操作符无法被识别,会导致更新不生效。检查实体类映射:确认
UserToolEngagements实体类的字段映射与数据库文档完全一致,比如t_maps、app_id的字段名是否通过@Field注解正确映射,避免因字段名不匹配导致更新失败。简化更新代码:推荐使用更简洁的
updateMulti方式,修改后的实现类代码如下:
@Component public class CustomUserMapsIdRepositoryImpl implements CustomUserMapsIdRepository { @Autowired MongoTemplate mongoTemplate; @Override public void updateUserMapsIdRepository(List<CustomUserMapsId> userMapsIdRepository, String app_id) { List<String> emails = userMapsIdRepository.parallelStream().map(i -> i.getEmail()).collect(Collectors.toList()); Query query = new Query(Criteria.where("email").in(emails)); Update update = new Update(); update.pull("t_maps.$[].app_id", app_id); UpdateResult result = mongoTemplate.updateMulti(query, update, UserToolEngagements.class); System.out.println("matchedCount = " + result.getMatchedCount()); System.out.println("modifiedCount = " + result.getModifiedCount()); } }
- 确认目标数据存在:检查目标文档的
t_maps.app_id中确实包含要移除的app_id值,避免因数据本身无该值导致修改计数为0。
内容的提问来源于stack exchange,提问作者Ramesh k
相关产品推荐
相关产品推荐

