项目中遇到批量保存或者更新文档,使用mongotemplate的upsert来处理,发现会直接覆盖之前的子集,而不是按照自己的规则去追加,或者更新子集
最后想到一个思路,记录一下
List<DayAir> dayAirList = mergeList(currentTime, syncMinutes);
if (!dayAirList.isEmpty()) {
//按照唯一键查询出对应文档
dayAirList.forEach(air -> {
Query query = new Query(Criteria.where("_id").is(air.getId()));
DayAir old = mongoTemplate.findOne(query, DayAir.class, "day_air");
if (old != null) {
air.setValues(MongoUtils.mergeDayAirValues(old.getValues(), air.getValues()));
}
});
//更新或者保存mongo,UNORDERED出现错误忽略继续执行
BulkOperations operations = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, "day_air");
List<Pair<Query, Update>> insertOrUpdateList = new ArrayList<>(dayAirList.size());
dayAirList.forEach(air -> {
String id = air.getId();
Query query = new Query(Criteria.where("_id").is(id).and("mp_id").is(air.getMpid()));
Update update = MongoUtils.fromDayAirExcludeNullFields(air);
Pair<Query, Update> pair = Pair.of(query, update);
insertOrUpdateList.add(pair);
});
operations.upsert(insertOrUpdateList);
operations.execute();
log.info("mongo-dayair保存" + dayAirList.size() + "条");
dayAirList.clear();
} else {
log.info("mongo-dayair暂无需要同步数据");
}
mongoutils文件
public static List<DayAirValue> mergeDayAirValues(List<DayAirValue> oldValues, List<DayAirValue> newValues) {
List<DayAirValue> dayAirValueList = new ArrayList<>(oldValues);
for (DayAirValue nv : newValues) {
for (DayAirValue ov : oldValues) {
//更新
if (ov.getPollutantCode() != null && ov.getPollutantCode().equals(nv.getPollutantCode())) {
//删除已存在的老ov
dayAirValueList.remove(ov);
}
}
}
//添加所有新的ov
dayAirValueList.addAll(newValues);
return dayAirValueList;
}
public static Update fromDayAirExcludeNullFields(DayAir air) {
Update update = new Update();
update.set("data_time", air.getDataTime());
update.set("mp_id", air.getMpid());
update.set("create_time", air.getCreateTime());
update.set("gd_id", air.getGdId());
update.set("mn", air.getMn());
update.set("protocol", air.getProtocol());
update.set("update_time", air.getUpdateTime());
List<Document> values = new ArrayList<>();
air.getValues().forEach(v -> {
Document value = Document.parse(JSONObject.toJSONString(v));
values.add(value);
});
update.set("values", values);
return update;
}