如何使用Mongo创建带字段、变量、索引的集合 实现邮箱唯一约束
解决方案
方案1:使用已引入的Mongoose实现(推荐,天然支持预定义字段+约束)
你代码中已经安装引入了Mongoose,它的Schema机制完全匹配「预定义字段+唯一性约束」的需求,比原生MongoClient操作更省心:
- 替换原来的原生MongoClient连接逻辑,改用Mongoose连接的同时定义用户Schema,Schema支持预定义所有允许的字段、字段类型,还可以给
email加unique: true配置强制唯一性,插入重复邮箱会直接抛出错误 - 基于Schema创建Model后,所有增删改查操作都用Model完成,自动校验字段和唯一性约束
- MongoDB插入文档时会自动生成唯一的
_id字段,做删除、更新操作直接用这个_id作为查询条件即可,不需要额外自定义唯一标识
修改后的完整代码示例:
const express= require ('express'); const mongoose = require('mongoose'); const bcrypt = require('bcrypt'); const cors = require('cors'); const saltRounds=10; const app = express(); app.use(cors()); app.use(express.json()); app.listen(3001,()=>{ console.log("Welcome,服务运行在3001端口"); }); // 1. 定义用户Schema(预定义字段+约束) const UserSchema = new mongoose.Schema({ name: String, identification: String, email: { type: String, unique: true, // 强制邮箱唯一 required: true // 可新增必填约束,避免不传邮箱的无效请求 }, password: String, cellphone: String, addedDate: Date, lastLoginDate: Date, role: String, speciality: String }) // 2. 创建数据模型,第三个参数指定集合名和你原有集合保持一致 const User = mongoose.model('User', UserSchema, 'users'); // 3. 用Mongoose连接数据库 mongoose.connect('mongodb+srv://admin:admin@cluster0.bs9d2.mongodb.net/ezbuy-database?retryWrites=true&w=majority', { useUnifiedTopology: true }) .then(() => console.log('Bienvenido a database mongo')) .catch(console.error) /*新增用户接口*/ app.post('/newuser', async (req, res) => { try { const hashedPwd = await bcrypt.hash(req.body.password, saltRounds) const user = new User({ ...req.body, password: hashedPwd, lastLoginDate: req.body.addedDate }) await user.save() res.send('Usuario Creado') } catch (err) { if (err.code === 11000) { // 捕获重复邮箱专属错误码 res.status(400).send('该邮箱已注册') } else { console.error(err) res.status(500).send('服务器错误') } } }) /*查询所有用户*/ app.get('/allusers', async (req, res) => { try { const users = await User.find() res.send(users) } catch (err) { console.error(err) res.status(500).send('查询失败') } }) /*根据ID查询单个用户*/ app.get('/userbyid/:id', async (req, res) => { try { const user = await User.findById(req.params.id) res.send(user) } catch (err) { console.error(err) res.status(500).send('查询失败') } }) /*更新用户接口示例*/ app.put('/updateuser/:id', async (req, res) => { try { await User.findByIdAndUpdate(req.params.id, req.body) res.send('更新成功') } catch (err) { console.error(err) res.status(500).send('更新失败') } }) /*删除用户接口示例*/ app.delete('/deleteuser/:id', async (req, res) => { try { await User.findByIdAndDelete(req.params.id) res.send('删除成功') } catch (err) { console.error(err) res.status(500).send('删除失败') } })
方案2:坚持用原生MongoClient实现
不需要修改原有连接逻辑,只要在获取到usersCollection之后新增一行代码创建唯一索引即可:
usersCollection.createIndex({email: 1}, {unique: true})
配置完成后也可以强制邮箱唯一性,插入重复数据会抛出11000错误码。
注意事项
- 如果你当前
users集合里已经存在重复邮箱的记录,创建唯一索引会失败,需要先清理重复数据再创建索引 - 做删改操作查询时,如果用原生MongoClient需要把前端传的字符串id转为
ObjectId类型才能匹配到对应文档:{_id: new ObjectId(前端传入的id字符串)}
内容的提问来源于stack exchange,提问作者klalvarez
相关产品推荐
相关产品推荐

