NodeJS+Mongoose更新用户后,Product模型owner信息首次请求未同步
问题:更新用户信息后,Product模型的owner字段未实时同步更新
我用NodeJS + Mongoose开发,MongoDB里有User和Product两个模型,用户与产品是一对多关联(一个用户拥有多个产品,一个产品对应一个用户)。更新用户信息时,只有User模型成功更新,Product模型中的owner信息还是旧数据;没有报错,但第二次发起请求时,Product模型才会同步更新用户信息。
用户控制器(USER CONTROLLER)
static async ChangeUser(req, res) { const {name, password, email, location} = req.body const changesToDo = { name, password, email, location } const user = await UserBusiness.GetUserByToken(req) if (user.status) { res.status(user.status).json({message: user.msg}) } const changedUser = await UserBusiness.ChangesToDo(changesToDo, user) if (changedUser.status) { res.status(changedUser.status).json({message: changedUser.msg}) } return res.status(200).json({message: "Alterações concluídas", user: changedUser}) }
业务逻辑层(USER BUSINESS)
static async ChangesToDo(changes, user) { if (!changes.name || changes.name.trim() == "") { changes.name = user.name } if (await this.UserExists(changes.email)) { return new EndMsg(400, "Email já está em uso") } if (!changes.email || changes.email.trim() == "") { changes.email = user.email } const pwdCompare = await bcrypt.compare(changes.password, user.password) if (pwdCompare || !changes.password || changes.password.trim() == "") { changes.password = user.password } else { const salt = bcrypt.genSaltSync(12) const hash = bcrypt.hashSync(changes.password, salt) changes.password = hash } if (!changes.location || changes.location.trim() == "") { changes.location = user.location } const updateUser = await UserRepository.UpdateUser(changes, user) if (updateUser.status) { return new EndMsg(updateUser.status, updateUser.msg) } return updateUser }
数据访问层(USER REPOSITORY)
static async UpdateUser(changes, user) { try { const update = await User.findByIdAndUpdate(user._id, {name: changes.name, password: changes.password, email: changes.email, location: user.location}) if (!update) { return new EndMsg(400, "Nao foi possível alterar os dados") } const otherUpdates = await Product.updateMany({'owner._id': user._id}, {owner: user}) console.log(otherUpdates) return update } catch(err) { console.log(err) return new EndMsg(500, err) } }
用户模型(USER MODEL)
const mongoose = require('../db/coon') const Product = require('../models/Product') const { Schema } = mongoose const User = mongoose.model( 'User', new Schema({ name: { type: String, required: true, }, password: { type: String, required: true, }, email: { type: String, required: true }, wishList: [{ type: Object }], location: { type: String }, product: Object }, {timestamps: true} ), ) module.exports = User
产品模型(PRODUCT MODEL)
const mongoose = require('../db/coon') const { Schema } = mongoose const Product = mongoose.model( 'Product', new Schema({ description: { type: String, required: true }, title: { type: String, required: true }, value: { type: Number, required: true }, quantity: { type: Number, required: true }, image: { type: String, }, rating: { type: Number }, secao: [{ type: Object }], owner:{ type: Object } }) ) module.exports = Product
问题原因
findByIdAndUpdate默认返回旧数据:Mongoose的findByIdAndUpdate方法默认返回更新前的用户文档,你用这个旧的user对象去更新Product的owner字段,自然不会同步最新的用户信息。- 第二次请求生效的原因:第二次请求时,
GetUserByToken会从数据库拉取已更新的用户数据,此时用新数据更新Product,就能同步成功。
解决方案
方案1:修复实时同步问题
修改UserRepository.UpdateUser,给findByIdAndUpdate添加{new: true}选项获取更新后的用户数据,并用它更新Product的owner字段,同时修正location参数错误:
static async UpdateUser(changes, user) { try { // 添加{new: true}获取更新后的用户数据 const updatedUser = await User.findByIdAndUpdate( user._id, {name: changes.name, password: changes.password, email: changes.email, location: changes.location}, {new: true} ) if (!updatedUser) { return new EndMsg(400, "Nao foi possível alterar os dados") } // 用更新后的用户对象同步Product的owner const otherUpdates = await Product.updateMany( {'owner._id': user._id}, {owner: updatedUser} ) console.log(otherUpdates) return updatedUser } catch(err) { console.log(err) return new EndMsg(500, err) } }
方案2:优化关联设计(推荐)
当前直接嵌入User对象到Product的owner字段会导致数据冗余和同步问题,改用Mongoose引用关联更合理:
- 修改Product模型的owner为引用类型:
// PRODUCT MODEL const Product = mongoose.model( 'Product', new Schema({ // 其他字段不变 owner:{ type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true } }) )
- 修改User模型添加products引用:
// USER MODEL const User = mongoose.model( 'User', new Schema({ // 其他字段不变 products: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Product' }] }, {timestamps: true} ), )
- 查询Product时通过
populate获取用户信息:
// 示例:查询产品并关联最新用户数据 const products = await Product.find().populate('owner', 'name email location');
这种设计无需手动同步用户数据,修改User后,查询Product时自动获取最新用户信息,同时避免数据冗余。
内容的提问来源于stack exchange,提问作者Emmanuel Medeiros
相关产品推荐
相关产品推荐

