Mongoose同Schema跨集合复制用户文档仅存默认值问题排查
问题原因
查询返回的user是Mongoose Document类实例,不是原生JavaScript对象。直接用展开运算符...展开时,只能获取到实例上的可枚举自有属性,无法拿到数据库查询返回的实际业务字段值,最终传给DeletedUser构造函数的有效字段为空,落库后就只会保留Schema中定义的默认值。
另外原代码还有两个不规范点:
- 调用Model构造函数生成实例是同步操作,前面加
await没有任何作用 save()是异步写入操作,未加await会存在写入未完成就执行后续逻辑、无法捕获写入异常的问题
解决方法
两种方案二选一即可:
- 方法1:查询时调用
.lean(),直接返回原生JS对象
加了.lean()后,查询返回的结果不再是Mongoose Document实例,就是普通对象,展开时可以正常拿到所有字段:const user = await User.findOne({ _id: id }).lean(); if (user) { // 如果不需要复用原用户_id,可放开下一行注释,让Mongo自动生成新_id // delete user._id; const deletedUser = new DeletedUser({ ...user, }); await deletedUser.save(); } - 方法2:对Document实例调用
.toObject()转为普通对象
如果查询后还需要用到Mongoose Document的内置方法,可以查询出实例后,调用自带的toObject()方法转成普通对象再展开:const user = await User.findOne({ _id: id }); if (user) { const userData = user.toObject(); // 如果不需要复用原用户_id、版本号字段,可放开下两行注释 // delete userData._id; // delete userData.__v; const deletedUser = new DeletedUser({ ...userData, }); await deletedUser.save(); }
补充说明:两个集合Schema完全一致的场景下,以上两种写法都可以保证写入
deleted-users集合的数据和原users集合数据完全一致。
内容的提问来源于stack exchange,提问作者warCommander
相关产品推荐
相关产品推荐

