保留关键字插入异常
背景
最近公司的某个应用的监控老是在某段时间报error日志增量过大。
排查过程
到kibana里查下那段时间error日志,发现每天在那段时间,都会抛出下面这段异常
org.springframework.data.mapping.MappingException: Map key ***.*** contains dots but no replacement was configured! Make sure map keys don't contain dots in the first place or configure an appropriate replacement!
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.potentiallyEscapeMapKey(MappingMongoConverter.java:873)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.prepareMapKey(MappingMongoConverter.java:855)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeMapInternal(MappingMongoConverter.java:822)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.createMap(MappingMongoConverter.java:743)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writePropertyInternal(MappingMongoConverter.java:628)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeProperties(MappingMongoConverter.java:596)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeInternal(MappingMongoConverter.java:572)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeInternal(MappingMongoConverter.java:545)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.write(MappingMongoConverter.java:489)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.write(MappingMongoConverter.java:94)
大概意思就是key里面包含"."。但是没有配置替代策略。叫我们确认key不包含".",或者配置替代策略。
Documen实体类如下:
@Data
@Accessors(chain = true)
@Document("extend_strategy")
public class ExtendStrategyDo {
/**
* 策略id
*/
@Indexed(unique = true)
private Integer strategyId;
/**
* 调用详情
*/
private Map<String, InvokeRecord> invokeInfo = new HashMap<>(0);
}
查了一下。发现.$
是Mongo的保留关键词。字段名内不能包含保留关键词。
虽然我们strategyId和invokeInfo不包含保留关键词。但是对于MongoDB中的键名,同样的限制也适用于Map的键和JSON对象的键。
因此,如果您的Map中的键名包含MongoDB不允许的字符(如点号和美元符号),或者超过了MongoDB的键名长度限制,插入操作可能会失败。
同样地,对于JSON对象的键名,也需要遵循相同的规则。在插入JSON文档时,如果键名不符合MongoDB的限制条件,可能会导致插入失败。
解决方法
将key中的.
替换成其他非保留关键词。我们业务中是非必要使用.
所以可以直接替换。如果非要使用怎么办呢。
可以在封装一下insert
、query
方法。插入前检查替换成别的字符。查询的时候替换回.
MongoTemplate Upsert异常
异常
mongo在使用mongoTemplate执行upsert的时候报如下错误:
org.springframework.dao.DataIntegrityViolationException: Performing an update on the path '_id' would modify the immutable field '_id'; nested exception is com.mongodb.MongoWriteException: Performing an update on the path '_id' would modify the immutable field '_id'
at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:112)
at org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:2902)\n\tat org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:587)
at org.springframework.data.mongodb.core.MongoTemplate.doUpdate(MongoTemplate.java:1636)
at org.springframework.data.mongodb.core.MongoTemplate.upsert(MongoTemplate.java:1570)
大概意思就是_id是不可变更的,但是你upsert操作变更了_id。所以报了异常。
解决方法
在更新过程中,把_id字段set null,就可以了。
评论