我先更新了猫鼬模型,然后使用实现简单视图计数器的$inc
运算符进行检索:
const profile = await Profile.findOneAndUpdate({ userName }, { $inc: { viewsCount: 1 } });
Profile
模式已启用timestamps
选项。问题是updatedAt
在viewsCount
更新期间被更新,这不是理想的行为。
我想在更新updatedAt
时禁用viewsCount
更新,最好通过执行尽可能少的查询。
我假设猫鼬的时间戳是通过预钩实现的。
findOneAndUpdate
如何在不更新viewsCount
的情况下递增updatedAt
?
可以否定时间戳挂钩的作用吗?
还有类似的问题可以解决updatedAt
更新的问题,但是解决方案不适合这种情况。
答案 0 :(得分:3)
在仔细研究过Mongoose文档之后,似乎简短的答案是否定的,没有设置findOneAndUpdate()
字段就无法调用updatedAt
。如果您查看文档here,则会清楚地指出所有用于更新的函数(findOneAndUpdate(),update()和bulkWrite())都会在查询中添加$set
运算符以设置{{1 }}。话虽这么说,但您确实有另一种建议,我会极力推荐。
变通
直接将createdAt和UpdatedAt字段添加到模型中,并摆脱时间戳记。当然,Mongoose为您处理它确实很好,但是最后,如果您必须尝试更改特定用例的时间戳设置功能,则最好自己完成。
如果您喜欢在调用updatedAt
或.save()
时设置了updatedAt和createdAt,则可以随时编写自己的中间件以添加操作。
.update()
我知道这不是理想的解决方案,但是坦率地说,我发现它更有用,因为它具有更好的控制力,并且猫鼬的意外行为更少。对自己的代码的控制越多越好。希望这会有所帮助!
答案 1 :(得分:3)
从mongoose 5.9.3开始,您可以将第三个参数设置为{ timestamps: false }
。
来自docs:
[options.timestamps = null]«Boolean»如果设置为false并且启用了模式级时间戳,请跳过此更新的时间戳。请注意,这使您可以覆盖时间戳。如果未设置架构级时间戳,则不执行任何操作。
答案 2 :(得分:1)
最简单的解决方法是直接与MongoDB API对话,而不让Mongoose处理更改。这段代码可以解决问题:
const profile = await Profile.collection.findOneAndUpdate({ userName }, { $inc: { viewsCount: 1 } });