Mongoose与Next.js中新增用户前校验数据库是否已存在该用户
解决用户重复存储的正确方案
前端校验刷新后失效的核心原因是:前端用户状态存在内存中,刷新后就会丢失,而且前端校验完全可以被绕过。所以必须在后端做强制校验,同时配合前端优化用户体验,双重保障避免重复存储。
一、后端核心校验(必做)
1. 先查询再创建
修改API的POST逻辑,在创建用户前先检查数据库中是否存在相同name和age的用户:
case "POST": try { const { name, age } = req.body; // 修正原逻辑错误:应该是||,否则只有两个字段都为空才报错 if (!name || !age) throw "invalid data"; // 关键步骤:查询是否存在同名同年龄的用户 const existingClient = await Client.findOne({ where: { name, age } }); if (existingClient) { return res.status(409).json({ success: false, error: "用户已存在" }); } const client = await Client.create({ name, age }); res.status(201).json({success:true, data:client}); } catch (error) { console.log(error); res.status(500).json({ success: false, error }); } break;
2. 数据库加联合唯一索引(终极保障)
直接在数据库层面给name和age加联合唯一约束,即使后端逻辑出问题,数据库也会拒绝插入重复数据。
如果用Sequelize,可以在模型定义中添加:
// Client模型文件 module.exports = (sequelize, DataTypes) => { const Client = sequelize.define('Client', { name: DataTypes.STRING, age: DataTypes.INTEGER }, { indexes: [ { unique: true, fields: ['name', 'age'] // 联合唯一索引 } ] }); return Client; };
执行数据库迁移后,该约束即可生效。
二、前端优化体验
前端可以提前做校验减少无效请求,同时处理后端返回的重复错误:
修改handleSubmitCreateClient函数:
async function handleSubmitCreateClient () { setIsLoading(true); try { // 前端预校验(仅优化体验,不能替代后端校验) const isDuplicate = users.some(user => user.name === name && user.age === age); if (isDuplicate) { Toast({ title: "用户已存在!", status: 'error', duration: 3000, isClosable: true, }); setIsLoading(false); return; } // 提交请求 const { data } = await api.post("/user", { name, age }) setUsers(users.concat(data.data)) setName ("") setAge ("") Toast ({ title: "Success!", status: 'success', duration: 3000, isClosable: true, }) } catch (error) { console.log(error); // 处理后端返回的重复错误 if (error.response?.status === 409) { Toast({ title: error.response.data.error, status: 'error', duration: 3000, isClosable: true, }); } else { Toast({ title: "添加失败!", status: 'error', duration: 3000, isClosable: true, }); } } finally { setIsLoading(false); } }
另外,页面刷新后要重新拉取最新用户列表,确保前端校验的准确性:
useEffect(() => { async function fetchUsers() { const { data } = await api.get("/user"); setUsers(data.data); } fetchUsers(); }, []);
内容的提问来源于stack exchange,提问作者thiago cerq
相关产品推荐
相关产品推荐

