如何避免向MongoDB的Collection Schema重复添加同一书籍?
解决方案:解决图书馆应用重复添加书籍问题
1. 确保MongoDB唯一索引生效
你在Schema里给title字段加了unique: true,但如果数据库未生成对应唯一索引,这个约束不会实际生效。可以通过两种方式修复:
- 方式一:Mongoose自动同步索引
在数据库连接代码中开启autoIndex(开发环境建议开启,生产环境关闭以优化性能):mongoose.connect(yourDbUrl, { autoIndex: true }); - 方式二:手动创建索引
直接在MongoDB Shell中执行命令,为collections集合创建title字段的唯一索引:db.collections.createIndex({ title: 1 }, { unique: true })
2. 在POST路由中处理重复键错误
当前代码里collection.save()遇到重复键错误时直接抛出给next(err),既没有给用户友好提示,也无法阻止重复提交。修改POST路由的错误处理逻辑:
collection.save((err) => { if (err) { // 捕获MongoDB重复键错误(错误码E11000) if (err.code === 11000) { // 获取当前书籍信息,用于页面渲染 const bookId = parseInt(req.params.title); const book = data.PopularBooks.find((book) => book.id === bookId); // 返回书籍页面并提示错误 return res.render("book", { book, errors: [{ msg: "该书籍已添加到你的图书馆" }] }); } return next(err); } res.redirect("/users/profile"); });
3. 前端提前禁用重复添加按钮
在书籍页面加载时,先查询当前书籍是否已在用户收藏中,若已存在则直接禁用添加按钮,从交互层面避免重复操作。
修改GET路由,传入书籍是否已收藏的状态:
router.get("/book/:title", async function (req, res, next) { const bookId = parseInt(req.params.title); const book = data.PopularBooks.find((book) => book.id === bookId); // 查询该书籍是否已存在于收藏中 const isAdded = await Collection.exists({ title: book.title }); res.render("book", { book, isAdded }); });
在页面模板(如EJS)中根据状态控制按钮:
<% if (!isAdded) { %> <form method="POST" action="/book/<%= book.id %>"> <input type="hidden" name="title" value="<%= book.title %>"> <input type="hidden" name="author" value="<%= book.author %>"> <input type="hidden" name="image" value="<%= book.image %>"> <button type="submit">添加到图书馆</button> </form> <% } else { %> <button disabled>已添加到图书馆</button> <% } %>
通过数据库约束、后端错误处理、前端交互三层优化,可彻底解决重复添加书籍的问题。
内容的提问来源于stack exchange,提问作者Dagger
相关产品推荐
相关产品推荐

