为啥 mongoose 的 deleteOne 和 findById 对已删除的 id 起作用

Posted

技术标签:

【中文标题】为啥 mongoose 的 deleteOne 和 findById 对已删除的 id 起作用【英文标题】:Why deleteOne & findById of mongoose work on deleted id为什么 mongoose 的 deleteOne 和 findById 对已删除的 id 起作用 【发布时间】:2020-08-05 16:00:58 【问题描述】:

目前正在使用 nodejs 开发与 MongoDB 数据库通信的 API,我注意到删除文档后的特殊行为。

确实,我的 API 有几个端点,允许检索数据库中的所有动物,使用相应的 id 检索特定的动物或删除特定的动物,再次使用要删除的文档的 id。

删除文档后会出现我不理解的结果。确实,如下图所示,当我删除名为“Johnny”的动物的文档时,通过其 ID 查找它或通过相同 ID 删除它的查询继续工作,即使 get 没有返回任何内容并且删除表示没有执行任何操作。

就我个人而言,我期望的行为与我为删除传递了错误的 id 相同(如下所示),但如果 id 已在数据库中分配,则即使在删除后查询也能正常工作。

MongoDB 是否有已删除文档的“缓存”,以便在意外删除时执行回滚?

您将在下面找到使用 find、deleteOne 和 findById 的不同端点


exports.getAllAnimal = (req, res, next) => 
    Animal.find().sort('customer' : 1)
    .then(animals => res.status(200).send(animals))
    .catch(error => res.status(400).send( error: error.message ));
;


exports.getOneAnimal = (req, res, next) => 
    Animal.findOne( _id: req.params.id )
        .then(animal => res.status(200).send(animal))
        .catch(error => res.status(400).send( error: error.message ));
;


exports.deleteAnimal = (req, res, next) => 
    Animal.deleteOne( _id: req.params.id )
        .then(thing => res.status(200).send( message : 'Animal successfully deleted'))
        .catch(error => res.status(400).send( error: error.message ));

;

【问题讨论】:

【参考方案1】:

MongoDB 不会在任何地方缓存已删除的 id。

问题是,当您说I passed a wrong id for a deletion ... 时,您传递的是一个长度相同但不是所需格式的 id。这就是 Mongoose 向您抛出错误的原因。

但是,如果你按照 MongoDB 的 id 结构创建一个数据库中不存在的 id 并对其进行操作,MongoDB 仍然会返回成功和空结果。

尝试使用5ea08034385a46666b05020f 并针对它运行.findById() 查询函数。它会成功返回一个空结果。

成功只表示操作成功,并不一定意味着它真的在数据库中找到了东西。

我无权访问您的数据库,因此 id 是随机生成的,但遵循以下 MongoDB ObjectId 规则:

12 字节的 ObjectId 值包括:

    一个 4 字节的时间戳值,代表 ObjectId 的创建,以 为单位 自 Unix 纪元以来的秒数 一个 5 字节的随机值 一个 3 字节递增计数器,初始化为随机值

生成任意 MongoDB ObjectId: https://observablehq.com/@hugodf/mongodb-objectid-generator

【讨论】:

感谢您的澄清!我是否必须在我的 API 中将 String ID 与 ObjectID 对象切换? 那么您的项目到底想做什么?我只是有点困惑。 这只是诚实的尝试。我想管理一个动物数据库,仅此而已。我想知道是否在“getOneAnimal”和“deleteAnimal”中我必须制作 ObjectId(req.params.id) 而不仅仅是 req.params.id 当您尝试执行其他操作时,也许您可​​以为每个动物添加其他唯一标识符,例如自定义昵称或 id。因为ObjectId 仅严格保留给 MongoDB。那么你在req.params.id 中传递了什么? Je suis français oui :) 好的,谢谢你的信息 :)

以上是关于为啥 mongoose 的 deleteOne 和 findById 对已删除的 id 起作用的主要内容,如果未能解决你的问题,请参考以下文章

MySQL外键约束On DeleteOn Update

Mongoose/Angular/Node:使用 deleteOne 方法的路由一直说对象已删除,但删除计数为零

《MongoDB入门教程》第21篇 CRUD之删除文档

《MongoDB入门教程》第21篇 CRUD之删除文档

MongoDB CRUD之D

数据库权限分配操作