【问题标题】:MongoDB (Mongoose) `findByIdAndDelete` not deleting (testing with Postman)MongoDB (Mongoose) `findByIdAndDelete` 不删除(用 Postman 测试)
【发布时间】:2020-08-08 15:03:48
【问题描述】:

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

app.js:

const express = require('express');
const bodyParser = require('body-parser');
const model = require('./model');

const app = express();

app.use(bodyParser.urlencoded({ extended: true }));

app.delete('/articles/:id', async (req, res) => {
    const articleID = req.params.id;
    console.log(`req.params.id: ${req.params.id}`);
    try {
        const response = await model.DBUtility.deleteOneArticleFromDB(articleID);
        res.status(200).json({message: response, app: 'wiki-api'});
    } catch (err) {
        res.json({message: err, app: 'wiki-api'});
    }
});

const port = 3000;
app.listen(port, () => {
    console.log(`Server started on port ${port}`);
});

model.js:

const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/wikiDB', {useNewUrlParser: true, useUnifiedTopology: true, useFindAndModify: false });

const articleSchema = new mongoose.Schema({
    title: String,
    content: String
});

const Article = mongoose.model('Article', articleSchema);

class DBUtility {

    static deleteOneArticleFromDB(articleID) {
        return new Promise((resolve, reject) => {
            Article.findByIdAndDelete(articleID, (err) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(`Deleted article ${articleID} successfully`);
                }
            });
        });
    }
}

exports.DBUtility = DBUtility;

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

{
    "_id" : "5c139771d79ac8eac11e754a",
    "title" : "API",
    "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."
}

/* 2 */
{
    "_id" : "5c1398aad79ac8eac11e7561",
    "title" : "Bootstrap",
    "content" : "This is a framework developed by Twitter that contains pre-made front-end templates for web design"
}

/* 3 */
{
    "_id" : "5c1398ecd79ac8eac11e7567",
    "title" : "DOM",
    "content" : "The Document Object Model is like an API for interacting with our HTML"
}

/* 4 */
{
    "_id" : "5ea2c188fa57aa1b6453eda5",
    "title" : "Node JS",
    "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—running 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.",
    "__v" : 0
}

/* 5 */
{
    "_id" : "5ea2d5304e19b11e0013a86a",
    "title" : "EJS",
    "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",
    "__v" : 0
}

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

如您所见,我得到了成功响应。但是,当我检查我的数据库时,该文档仍然存在(我已经单击了几次刷新并使用 GET 请求返回所有文章进行了测试,结果表明该文章仍然存在):

这是终端输出:

[nodemon] starting `node app.js`
Server started on port 3000
req.params.id: 5ea2d5304e19b11e0013a86a

我已经做了两天了。我已经检查了所有以前与我的标题相似的 SO 帖子,但我看不到适用于我的问题的帖子。我不明白我要去哪里错了!!任何帮助将不胜感激。

更新

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

【问题讨论】:

    标签: node.js mongodb express mongoose


    【解决方案1】:

    在 MongoDB 中,_id 属性的类型为 ObjectId
    我遇到了同样的问题,并通过传递 ObjectId 来解决它。

    您尝试过以下方法吗?

    const Mongoose = require('mongoose');
    const articleId = Mongoose.Types.ObjectId(req.params.id);
    

    【讨论】:

    • 感谢 Reqven 的建议。我像这样修改了我的代码(对不起,我希望 SO 允许评论回复具有良好的代码格式):static deleteOneArticleFromDB(articleID) { const objectId = mongoose.Types.ObjectId(articleID); return new Promise((resolve, reject) => { Article.findByIdAndDelete(objectId, (err) => { if (err) { reject(err); } else { resolve(Deleted article ${objectId}successfully); } }); }); }
    • 不幸的是,它仍然不起作用。与 JSON 相同的响应显示已删除文档及其 ID 成功,但该文档仍在数据库中。我刚刚检查了数据库并对所有文章进行了 GET 请求,其中包括应该删除的文章。
    • 我尝试修改 app.js 一侧的代码,如下所示:app.delete('/articles/:id', async (req, res) => { const articleID = mongoose.Types.ObjectId(req.params.id); try { const response = await model.DBUtility.deleteOneArticleFromDB(articleID); res.status(200).json({message: response, app: 'wiki-api'}); .... 。但还是不行。相同的成功响应,但文档不会从数据库中删除
    • 我会继续努力,如果我有任何地方,请发布答案。
    【解决方案2】:

    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
    

    更新

    根据这张图片

    您似乎手动插入了数据,并且这些数据包含_id 作为字符串,因为_id 的类型在这里是一个字符串,正如您在这张图片中看到的那样

    我建议你让MongoDB自己设置_id

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

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

    希望这可以解决问题



    更新 2

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

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

    所以当你试图通过传递 id 来删除一些文章时,nodeJS 一个 express 会将它传递给第一个匹配的路由,因为它不知道你发送的 params,它正在搜索基础 url route,所以它处理与url匹配的第一条路线:'/articles/something',以此为文章标题

    然后调用deleteOneArticleByTitleFromDB方法

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

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

    这样您就可以通过 Id 路由定义删除,如下所示

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

    或任何你想要的,除了当前的

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

    【讨论】:

    • 对我迟到的回复道歉,我正在尝试您的解决方案以及其他解决方案。谢谢您的建议。我使用的是 Mongoose 版本 5.9.10,该文档包含此 api。我已经尝试了你所有的建议,不幸的是没有任何效果。我已经尝试了您的解决方案和Reqven 的这篇文章中的第一个解决方案的组合。我尝试了许多不同的组合,但没有任何效果。我使用deleteOne 完成了另一个基于title 字段的DELETE api,并且立即生效。我使用了deleteOne,但使用了_id 查询,你猜怎么着,它也不起作用。
    • 很明显,ID 的某些问题无法正常工作。我已经在这个问题上讨论了 4 天了。这是一次非常令人沮丧的经历,坦率地说,我现在已经没有所有的想法了。
    • 我试过const articleID = req.params.id.toString().trim();然后把它传递给apitry { const response = await model.DBUtility.deleteOneArticleByIdFromDB(articleID); res.json({message: response, app: 'wiki-api'}); } catch (err) { res.json({message: err, app: 'wiki-api'}); }
    • 我试过const articleID = mongoose.Types.ObjectId(req.params.id);。没用。然后我尝试了const articleID = req.params.id.toString().trim(); const id = mongoose.Types.ObjectId(articleID); 的组合。没用。
    • 检查了github中的代码后,我又更新了我的答案,你能检查一下吗?
    猜你喜欢
    • 2021-06-03
    • 2017-12-24
    • 1970-01-01
    • 2021-02-08
    • 2021-12-28
    • 2021-04-01
    • 2013-09-04
    • 2020-03-31
    • 2016-11-19
    相关资源
    最近更新 更多