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

Node.js+Mongoose删除MongoDB数据:一键有效一键无效求排查

Why Your Second Delete Route Isn't Working (And How to Fix It)

Hey Sam, let's break down what's going on here—your issue boils down to how Express matches route patterns, and a subtle conflict between your two delete routes.

The Root Problem

Express uses pattern matching to route requests, and your two delete routes have identical structural patterns once you account for dynamic parameters:

  • First route: /myprojects/:id/cost/:labour_id/remove
  • Second route: /myprojects/:id/cost/:tool_id/remove

To Express, :labour_id and :tool_id are just generic placeholders for dynamic values—they don't make the routes unique. So when you click the second button (triggering a URL like /myprojects/123/cost/456/remove), Express immediately matches it to the first route and never reaches the second one.

Fix 1: Add a Unique Segment to the Route Path

The cleanest solution is to modify the second route to include a distinct segment so Express can tell them apart. Here's how to update your code:

Updated EJS Button for Tools

<td class="td21">
  <a href="/myprojects/<%= project._id %>/cost/tool/<%= tool._id %>/remove">
    <button type="button" class="btn btn-danger">Remove</button>
  </a>
</td>

Updated Tool Delete Route

app.get("/myprojects/:id/cost/tool/:tool_id/remove", function(req, res){
  Tool.findByIdAndRemove(req.params.tool_id, function(err){
    if(err){
      console.log(err);
    }else{
      Project.findById(req.params.id, function(err, foundProject){
        if(err){
          console.log(err);
        }else{
          res.redirect("/myprojects/" + req.params.id + "/cost");
        }
      });
    }
  });
});

Fix 2: Use Query Parameters to Distinguish Item Type

If you prefer to keep a single route structure, you can add a query parameter to specify whether you're deleting a labour or tool entry:

Updated EJS Button for Tools

<td class="td21">
  <a href="/myprojects/<%= project._id %>/cost/<%= tool._id %>/remove?type=tool">
    <button type="button" class="btn btn-danger">Remove</button>
  </a>
</td>

Combined Delete Route

app.get("/myprojects/:id/cost/:item_id/remove", function(req, res){
  const itemId = req.params.item_id;
  const itemType = req.query.type;

  // Select the correct model based on query param
  let ModelToDelete;
  if(itemType === "labour"){
    ModelToDelete = Labour;
  } else if(itemType === "tool"){
    ModelToDelete = Tool;
  } else {
    return res.status(400).send("Invalid item type");
  }

  ModelToDelete.findByIdAndRemove(itemId, function(err){
    if(err){
      console.log(err);
    }else{
      res.redirect("/myprojects/" + req.params.id + "/cost");
    }
  });
});

Quick Best Practice Note

While your current setup works, using GET requests for destructive actions like deletion isn't ideal (GET requests can be cached, bookmarked, or accidentally triggered). For production apps, consider using DELETE HTTP methods with forms or AJAX instead—but fixing the route conflict will get your second button working immediately.

内容的提问来源于stack exchange,提问作者Sam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:53:52