You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 21:05:19