因为bulk.upsert()和mongoTemplate.upsert()的内部对document这种全文档更新的实现不一样,所以导致批量执行报错,下面说明。 以下代码执行没有问题,正常更新
Document document = new Document();
mongoTemplate.getConverter().write(xxxPO, document);
Update update = Update.fromDocument(document);
mongoTemplate.upsert(Query.query(Criteria.where("_id").is(xxxPO.getId())),
update, MongoConst.COLLECTION_NAME);
但是同样的操作放到bulk里就会失败,但是如果不用document转换这种方式,直接用update.set是没有问题的,所以问题就出在update上面,
BulkOperations bulk = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, xxxPO.class);
List<Pair<Query, Update>> updates = udps.stream().map(p -> {
Document document = new Document();
mongoTemplate.getConverter().write(p, document);
Update update = Update.fromDocument(document);
Query query = Query.query(Criteria.where("_id").is(p.getId()));
Pair<Query, Update> pair = Pair.of(query, update);
return pair;
}).collect(Collectors.toList());
bulk.upsert(updates);
执行报错
java.lang.IllegalArgumentException: Invalid BSON field name xxx
打印document转换完的update对象:
{
"isolated":false,
"arrayFilters":[
],
"updateObject":{
"scenicSpotProductId":"4915367",
"scenicSpotRuleId":"4915368",
"ticketKind":"2",
"startDate":"2021-12-31",
"endDate":"2021-12-31",
"weekDay":"1,2,3,4,5,6,7",
"stock":99,
"sellPrice":74,
"settlementPrice":74,
"replaceRule":0,
"merchantCode":"320044720",
"createTime":1637050139710,
"updateTime":1637052559680,
"floatPriceManually":false,
"floatPriceType":1
}
}
打印Update.set(key, value)方法返回的update对象
{
"isolated":false,
"arrayFilters":[
],
"updateObject":{
"$set":{
"scenicSpotProductId":"4915367",
"sellPrice":74,
"settlementPrice":74,
"updateTime":1637053306267
}
}
}
发现document转换过的少了一层“$set”节点,但是update对象不支持直接改updateObject,所以在源对象上做文章,外面包一层map再转就可以了;
List<Pair<Query, Update>> updates = udps.stream().map(p -> {
Document document = new Document();
Map<String, xxxPO> s = Maps.newHashMap();
s.put("$set", p);
mongoTemplate.getConverter().write(s, document);
Update update = Update.fromDocument(document);
Query query = Query.query(Criteria.where("_id").is(p.getId()));
Pair<Query, Update> pair = Pair.of(query, update);
return pair;
}).collect(Collectors.toList());
bulk.upsert(updates);
第一段代码没问题是因为mongoTemplate下面的更新方法内部做了转换处理;
bulk的所有更新方法都有这个问题,初步测试是没什么问题,只是文档里的_class会变成
java.util.HashMap,目前对业务没有影响,后续再观察。
以下是mongo版本和springdata版本,其它版本未测试。
mongodb 3.4.6
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>