MongoDB (Mongoose) `findByIdAndDelete` 不删除(使用 Postman 测试)

Haz*_*ldo 2 mongoose mongodb node.js express

我的 Mongoose 代码位于单独的model.js文件中,而用于处理 http 请求的 Express 代码位于app.js. 我只是在为一个虚构的 wiki 文章网站练习创建 API 并在 Postman 上测试它们。我正在努力让它工作的 api 正在删除一篇文章。(注意:为了简洁起见,我只包含了有问题的代码,即app.delete(\'/articles/:id\' ....from app.js,以及它调用的静态方法model.js ,以及它从-deleteOneArticleFromDB(articleID)

\n\n

app.js:

\n\n
const express = require(\'express\');\nconst bodyParser = require(\'body-parser\');\nconst model = require(\'./model\');\n\nconst app = express();\n\napp.use(bodyParser.urlencoded({ extended: true }));\n\napp.delete(\'/articles/:id\', async (req, res) => {\n    const articleID = req.params.id;\n    console.log(`req.params.id: ${req.params.id}`);\n    try {\n        const response = await model.DBUtility.deleteOneArticleFromDB(articleID);\n        res.status(200).json({message: response, app: \'wiki-api\'});\n    } catch (err) {\n        res.json({message: err, app: \'wiki-api\'});\n    }\n});\n\nconst port = 3000;\napp.listen(port, () => {\n    console.log(`Server started on port ${port}`);\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

model.js:

\n\n
const mongoose = require(\'mongoose\');\n\nmongoose.connect(\'mongodb://localhost:27017/wikiDB\', {useNewUrlParser: true, useUnifiedTopology: true, useFindAndModify: false });\n\nconst articleSchema = new mongoose.Schema({\n    title: String,\n    content: String\n});\n\nconst Article = mongoose.model(\'Article\', articleSchema);\n\nclass DBUtility {\n\n    static deleteOneArticleFromDB(articleID) {\n        return new Promise((resolve, reject) => {\n            Article.findByIdAndDelete(articleID, (err) => {\n                if (err) {\n                    reject(err);\n                } else {\n                    resolve(`Deleted article ${articleID} successfully`);\n                }\n            });\n        });\n    }\n}\n\nexports.DBUtility = DBUtility;\n
Run Code Online (Sandbox Code Playgroud)\n\n

我的数据库中有 5 篇文章(5 个文档):

\n\n
{\n    "_id" : "5c139771d79ac8eac11e754a",\n    "title" : "API",\n    "content" : "API stands for Application Programming Interface. It is a set of subroutine definitions, communication protocols, and tools for building software. In general terms, it is a set of clearly defined methods of communication among various components. A good API makes it easier to develop a computer program by providing all the building blocks, which are then put together by the programmer."\n}\n\n/* 2 */\n{\n    "_id" : "5c1398aad79ac8eac11e7561",\n    "title" : "Bootstrap",\n    "content" : "This is a framework developed by Twitter that contains pre-made front-end templates for web design"\n}\n\n/* 3 */\n{\n    "_id" : "5c1398ecd79ac8eac11e7567",\n    "title" : "DOM",\n    "content" : "The Document Object Model is like an API for interacting with our HTML"\n}\n\n/* 4 */\n{\n    "_id" : "5ea2c188fa57aa1b6453eda5",\n    "title" : "Node JS",\n    "content" : "Node.js is an open-source, cross-platform, JavaScript runtime environment that executes JavaScript code outside of a web browser. Node.js lets developers use JavaScript to write command line tools and for server-side scripting\xe2\x80\x94running scripts server-side to produce dynamic web page content before the page is sent to the user\'s web browser. Consequently, Node.js represents a \\"JavaScript everywhere\\" paradigm,[6] unifying web-application development around a single programming language, rather than different languages for server- and client-side scripts.",\n    "__v" : 0\n}\n\n/* 5 */\n{\n    "_id" : "5ea2d5304e19b11e0013a86a",\n    "title" : "EJS",\n    "content" : "EJS is a simple templating language that lets you generate HTML markup with plain JavaScript. No religiousness about how to organize things. No reinvention of iteration and control-flow. It\'s just plain JavaScript",\n    "__v" : 0\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我正在尝试删除最后一篇标题为 的文章(文档)EJS。所以在 Postman 中我运行 http 请求如下:

\n\n

在此输入图像描述

\n\n

如您所见,我得到了成功的响应。但是,当我检查数据库时,该文档仍然存在(我已多次单击刷新,并使用 GET 请求测试它以返回所有文章,这表明该文章仍然存在):\n在此输入图像描述

\n\n

这是终端输出:

\n\n
[nodemon] starting `node app.js`\nServer started on port 3000\nreq.params.id: 5ea2d5304e19b11e0013a86a\n
Run Code Online (Sandbox Code Playgroud)\n\n

我已经研究这个问题两天了。我已经检查了之前所有与我的标题相似的 SO 帖子,但我找不到适用于我的问题的帖子。我不明白我哪里错了!!任何帮助将非常感激。

\n\n

更新

\n\n

根据 Mohammed Yousry 下面的解决方案,我意识到我_id使用字符串手动添加了该字段,因为我正在遵循教程。因此不允许 MongoDB 创建该_id字段,作为ObjectId. 因此,我的_id字段是 String 类型而不是 ObjectId 类型。因此,为了解决这个问题,我从数据库中删除了所有文档并重新添加它们,使用 POSTMAN 和我创建的 POST 方法 - 用于创建/添加新的文章文档到数据库,仅提供请求正文中的title和字段。因此,允许 MongoDB为每个文章文档content创建字段。_id现在在数据库中该_id字段的类型为ObjectId。这仍然没有完全解决我的问题,但又向前迈进了一步。仍在努力达成解决方案。请参阅下面解决方案部分的讨论。

\n\n

在此输入图像描述

\n

Moh*_*sry 5

1-可能是你的mongoose版本不支持findByIdAndDelete

尝试findByIdAndRemove代替

2-您可以将 id 作为字符串或 objectId 传递给该方法

确保您传递的 ID 正确且不带任何空格

const articleID = req.params.id.toString().trim(); // trim will remove any spaces before or after the id
Run Code Online (Sandbox Code Playgroud)

更新

根据这张图片

在此输入图像描述

看来您已手动插入数据,并且这些数据包含作为_id字符串,因为_id这里的类型是字符串,正如您在此图中看到的那样

我建议你让自己MongoDB设置_id

如果您可以将_id类型更改为ObjectId

或者如果您无法更改 的类型_id,您可以备份您的文章,然后手动删除所有这些文章并在没有 _id 的情况下再次添加它们,让 mongoDB 设置该 _id,然后再次尝试您的代码

希望这可以解决问题



更新2

检查了 github 中的代码后,我知道你出现这种奇怪行为的原因

app.route('/articles/:articleTitle')1-您在路线之前定义了路线app.delete('/articles/:id'

因此,当您尝试通过传递 id 来删除某些文章时,nodeJS Express 会将其传递给第一个匹配的路由,因为它不知道您发送的内容,它正在搜索中的params基础,因此它处理第一个路由与:匹配,将其作为文章标题urlrouteurl'/articles/something'

然后调用该deleteOneArticleByTitleFromDB方法

然后,MongoDB 正在搜索一些标题为您传递的 id 的文章,它什么也没找到,然后,它不会删除任何文章

2-我建议你不要定义一些具有相同基本url的路由

所以你可以通过 Id 路由定义删除,如下所示

app.delete('/arti/cles/:id', async (req, res) => // note the slash inside articles word
Run Code Online (Sandbox Code Playgroud)

或除当前的之外的任何您想要的内容

这样你就可以避免路线之间的这种矛盾