Mongoose中跨Schema复制数据的问题求助
问题描述
我是Mongoose新手,正在开发一个简单Web应用,需要将一个Schema的数据关联到另一个Schema中。已在GrocerySchema和ListSchema中建立双向关联,尝试把选中的grocery添加到list的groceries数组,但编写POST路由时无法同时获取list和grocery的ID——表单只能拿到其中一个ID,附上相关代码寻求帮助。
相关代码
Schema定义
const GrocerySchema = new Schema({ name: String, aisle: Number, list: { type: Schema.Types.ObjectId, ref: "List", }, }); const ListSchema = new Schema({ name: String, groceries: [ { type: Schema.Types.ObjectId, ref: "Grocery", }, ], });
前端表单代码
<ul> <% groceries.forEach(function(grocery) { %> <li> <a href="/groceries/<%= grocery.id %>"> <%= grocery.name %> <%=`Aisle: ${grocery.aisle}`%></a> <form action="/list/<%= list.id %>/add" method="post"> <!-- 这里应该用grocery.id吗? --> <button>添加到清单</button> </form> </li> <% }); %> </ul>
解决方案
要同时获取两个ID,有两种简单可行的实现方式:
方法1:用隐藏字段传递另一个ID
把grocery的ID作为隐藏输入字段嵌入表单,提交时就能同时拿到URL里的list ID和表单中的grocery ID:
<ul> <% groceries.forEach(function(grocery) { %> <li> <a href="/groceries/<%= grocery.id %>"> <%= grocery.name %> <%=`Aisle: ${grocery.aisle}`%></a> <form action="/list/<%= list.id %>/add" method="post"> <!-- 添加隐藏字段传递grocery ID --> <input type="hidden" name="groceryId" value="<%= grocery.id %>"> <button>添加到清单</button> </form> </li> <% }); %> </ul>
后端POST路由中,从req.params.listId获取list的ID,从req.body.groceryId获取grocery的ID:
app.post('/list/:listId/add', async (req, res) => { try { const list = await List.findById(req.params.listId); const grocery = await Grocery.findById(req.body.groceryId); // 更新list的groceries数组 list.groceries.push(grocery._id); await list.save(); // 同步更新grocery的list字段,保证双向关联数据一致 grocery.list = list._id; await grocery.save(); res.redirect(`/list/${list._id}`); // 重定向到目标清单页面 } catch (err) { console.error(err); res.status(500).send('添加失败'); } });
方法2:将两个ID都放入URL路径
修改表单的action属性,同时包含list和grocery的ID:
<ul> <% groceries.forEach(function(grocery) { %> <li> <a href="/groceries/<%= grocery.id %>"> <%= grocery.name %> <%=`Aisle: ${grocery.aisle}`%></a> <form action="/list/<%= list.id %>/add/<%= grocery.id %>" method="post"> <button>添加到清单</button> </form> </li> <% }); %> </ul>
后端路由对应调整为:
app.post('/list/:listId/add/:groceryId', async (req, res) => { try { const list = await List.findById(req.params.listId); const grocery = await Grocery.findById(req.params.groceryId); list.groceries.push(grocery._id); await list.save(); grocery.list = list._id; await grocery.save(); res.redirect(`/list/${list._id}`); } catch (err) { console.error(err); res.status(500).send('添加失败'); } });
注意事项
- 确保
Grocery和List两个模型已正确定义并导出 - 操作数据库时建议用
async/await处理异步逻辑,避免回调嵌套 - 双向关联需同时更新两边字段,保证数据一致性
内容的提问来源于stack exchange,提问作者JC42
相关产品推荐
相关产品推荐

