findOneAndDelete()和findOneAndRemove()有什么区别?

56

我无法区分 findOneAndDelete()findOneAndRemove()mongoose 文档中的区别。

Query.prototype.findOneAndDelete()

此函数与 Model.findOneAndRemove() 稍有不同,因为 findOneAndRemove() 变成了 MongoDB 的 findAndModify() 命令,而不是 findOneAndDelete() 命令。对于大多数 mongoose 使用场景来说,这种区别纯粹是学究式的。 您应该使用 findOneAndDelete(),除非您有充分的理由不这样做。


3
除非你有充分的理由,否则应该使用findOneAndDelete()方法。什么样的理由算是充分的呢? - g1ji
12
findOneAndDelete() 执行 MongoDB 的 findOneAndDelete() 命令,而 findOneAndRemove() 则执行 MongoDB 的 findAndModify() 命令。 - Abhijith S
1
为什么在执行 MongoDB 的 findAndModify() 后,findOneAndRemove() 会删除集合中的文档? - g1ji
正如@AlexBlex所建议的那样,我们可以根据使用情况使用其中之一。此外,与另一个相比,findOneAndDelete()是在最近版本中引入的。 - Bharathvaj Ganesan
请看这里:Here ya go - stacksonstacks
显示剩余4条评论
8个回答

14
TLDR: 除非有充分的理由,否则应该使用findOneAndDelete()。
详细回答:
根据Mongoose文档中的描述,findOneAndDelete()函数与Model.findOneAndRemove()稍有不同。Model.findOneAndRemove()会变成一个MongoDB的findAndModify()命令,而不是一个findOneAndDelete()命令。对于大多数mongoose用例来说,这种区别纯粹是学究式的。除非您有充分的理由,否则应该使用findOneAndDelete()。 Mongoose Docs findOneAndDelete

2
除非你有充分的理由,否则应该使用findOneAndDelete()。这样的理由是什么? - Normal

4

他们两个都很相似,除了 findOneAndRemove 会使用 findAndModify 并带有删除标记,与 findOneAndDelete 相比,时间复杂度稍高,因为你正在进行更新。删除总是更快的。


这两个函数在传输到 MongoDB 时发送相同的命令,时间复杂度没有区别。 - ZachB
根据mongoose文档,它们不会发送相同的命令:https://mongoosejs.com/docs/api.html#model_Model.findOneAndDelete 还请参阅MongoDB文档:https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/ https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndDelete/ 根据我的经验,在删除大量数据时,这两个命令之间会出现延迟,因为findAndModify会返回数据。 - Manni Dula
驱动程序将命令转换,两者都返回数据。 - ZachB
"findOneAndDelete()查找匹配的文档,将其删除,并将找到的文档(如果有)传递给回调。根据mongoose文档,findOneAndDelete还会返回已删除的文档(如果有)。" - Isuru Maldeniya

4
在 MongoDB 原生客户端中(Mongoose 不同),将 { remove: true } 作为参数传递给 findAndModify 会删除找到的文档,此时其行为与 findOneAndDelete 类似。但是,在使用其他选项时存在一些差异:
  • findAndModify 方法需要 5 个参数:querysortdoc(更新对象),optionscallback。而 findOneAndDelete 只需要 3 个参数(filter 或查询,optionscallback)。
  • findAndModifyoptions 包括写入关注的 wwtimeoutj,如:

    “从 MongoDB 请求写操作的确认级别,用于独立 mongod 或副本集或分片集群。”或简单地说,用于报告写操作成功的可用保障级别。

    findOneAndDeleteoptions 不包括写操作的配置。

  • findAndModify 允许您同时返回新文档并将其删除。

示例:

// Simple findAndModify command returning the new document and
  // removing it at the same time
  collection.findAndModify({b:1}, [['b', 1]], {$set:{deleted: Date()}}, {remove:true}, calback)

2
我认为这些差异实际上并不存在。(1)findOneAndDelete确实需要一个排序选项。(2)findOneAndDelete需要一个writeConcern选项,但是它没有被记录在文档中。(3)findOneAndDelete还会返回已删除的文档。 - ZachB
是的 @ZachB,findOneAndDelete() 方法还会返回被删除的文档(如果有)。 - Isuru Maldeniya

2
这里的其他答案有很多错误信息。它们在所有意义上都是相同的,您应该只使用findOneAndDelete()
Mongoose的Model.findOneAndRemove(query)变成了MongoDB的findAndModify({query, remove: true})
Mongoose的Model.findOneAndDelete()变成了MongoDB的findOneAndDelete()。但是,MongoDB驱动程序会将findOneAndDelete(query, opts)转换为findAndModify({query, remove: true})(src)。因此,在数据库中它们执行完全相同的操作。
两者使用相同的选项。
两者返回已删除文档。

那么,如果两个函数最终都实现了相同的目的,那么拥有两个函数的意义是什么呢? - Normal
几乎可以确定是遗留的垃圾代码。 - ZachB

1
在mongoose中,findOneAndDelete的用法与findOneAndRemove相同。它们都通过JSON属性查找对象,然后进行删除并在删除后返回该对象。当您使用原生mongodb作为数据库时,findOneAndDelete可能对您有用,但在mongoose的情况下,它已被弃用,我建议您根据最新的mongoose和nodejs配置使用findOneAndDelete来执行操作。https://github.com/Automattic/mongoose/issues/6880

1
我从GitHub上的讨论中得知:DeprecationWarning: collection.remove is deprecated. Use deleteOne, deleteMany, or bulkWrite instead. 你想说的是,findOneAndRemove 使用了 collection.remove,而 findOneAndDelete 则使用了 (collection.deleteOnecollection.deleteMany)? - g1ji

1

以下是摘自mongoose文档中Model.findOneAndDelete()部分的确切区别:

“此函数与Model.findOneAndRemove()略有不同,因为findOneAndRemove()变成了MongoDB findAndModify()命令,而不是findOneAndDelete()命令。对于大多数mongoose用例来说,这种区别纯粹是学究式的。除非您有充分的理由,否则应该使用findOneAndDelete()。”

这是它的链接: https://mongoosejs.com/docs/api.html#model_Model.findOneAndDelete


请注意,findOneAndDelete()方法也会返回已删除的文档。 - mabdullahse

0

findOneAndRemove返回已删除的文档,因此如果您删除了一个文档,但后来决定不应该删除它,可以将其重新插入到数据库中。在删除文档之前确保逻辑正确比之后进行检查更好。

findOneAndDelete具有排序参数,可用于影响要更新的文档。它还具有TimeLimit参数,可控制操作必须完成的时间限制。


两者都返回已删除的文档。两者都有一个排序参数。两者都有时间限制。 - ZachB

-1
我建议您使用findOneAndDelete()。Mongoose提供了使用ORM处理数据的功能和直接写入数据库的功能,其中findOneAndDelete()是后者之一。直接写入数据库更危险,因为您可能会冒着不调用中间件或验证器的风险,可能会向数据库提交部分或不完整的数据。请注意,我说它是危险的,而不是绝对危险的,findOneAndDelete()只是通过ORM添加了安全性。

1
两者都通过Mongoose(ORM)进行,并具有相同的中间件注意事项。 - ZachB

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接