Mongoose 5.2.10中Map类型子文档报'-1'字段创建错误求助
解决Mongoose 5.2.10中子文档Map类型引发的
-1字段创建错误 这个问题是Mongoose 5.x早期版本对子文档数组中的Map类型处理存在的已知bug,根源是Mongoose的变更追踪系统错误地将不存在的数组索引(-1)对应的Map字段标记为修改状态,导致生成无效的更新操作发送给MongoDB,从而抛出Cannot create field '-1'的错误。
因为你暂时无法升级版本,这里有几个可行的临时解决方案:
1. 手动清除错误的修改路径
在调用document.save()之前,手动移除activePaths中那些包含child.-1的无效修改路径:
Document.findById(theDocumentId, function (err, document) { // 添加不含map schema的childs // 新增:清除错误标记的修改路径 const modifyPaths = document.$__.activePaths.states.modify; Object.keys(modifyPaths).forEach(path => { if (path.startsWith('child.-1')) { delete modifyPaths[path]; } }); return document.save().then( function(returnDocument) { // 后续逻辑 }).catch(function (err) { console.log(err) }) })
这个操作会直接删掉那些误标记的无效路径,避免Mongoose向MongoDB发送错误的更新指令。
2. 重置子文档的变更状态
如果确认新增的子文档没有修改maps字段,可以手动重置子文档的变更追踪状态,让Mongoose忽略它的误判:
Document.findById(theDocumentId, function (err, document) { // 添加不含map schema的childs // 新增:重置所有子文档的变更状态 document.child.forEach(childDoc => { childDoc.$__.activePaths.reset(); }); return document.save().then( function(returnDocument) { // 后续逻辑 }).catch(function (err) { console.log(err) }) })
注意:如果实际修改了子文档中的内容,不要使用这个方法,否则会丢失你的变更。
3. 给Map字段设置默认空值
在定义childSchema时,给maps字段设置一个默认的空Map,避免Mongoose因为字段初始值为undefined而触发错误的变更标记:
var childSchema = new mongoose.Schema({ _id: { type: String, required: true }, maps: { type: Map, of: mapSchema, default: () => new Map() // 新增默认值 } }, { id: false });
这样新增子文档时maps会自动初始化为空Map,Mongoose的变更追踪系统就不会误标记不存在的路径了。
另外补充:这个bug在Mongoose 5.3及之后的版本中已经被官方修复,所以如果后续有升级条件,升级到最新的5.x版本(或者更高版本)是彻底解决问题的最佳方案。
内容的提问来源于stack exchange,提问作者jzwiesler
相关产品推荐
相关产品推荐

