mongodb - MongoDB 中的条件更新

标签 mongodb design-patterns

我已经在 LinkedIn 上回答了这个问题,我认为分享它有用且有趣。问题是:

“假设我们有像 {_id: ..., data: ..., timestamp: ...} 这样的文档。

有什么方法可以编写满足以下规则的更新条件:

1 如果后面没有_id的文档则插入这个文档;

2 如果存在具有以下_id 的文档则

2.1 如果新的时间戳大于存储的时间戳则更新data;

2.2 否则什么也不做”

最佳答案

下面的解决方案应该可以解决问题,您只需要忽略双键错误。示例在 Mongo shell 中给出:

> var lastUpdateTime = ISODate("2013-09-10")
> var newUpdateTime = ISODate("2013-09-12")
>
> lastUpdateTime
ISODate("2013-09-10T00:00:00Z")
> newUpdateTime
ISODate("2013-09-12T00:00:00Z")
>
> var id = new ObjectId()
> id
ObjectId("52310502f3bf4823f81e7fc9")
>
> // collection is empty, first update will do insert:
> db.testcol.update(
... {"_id" : id, "ts" : { $lt : lastUpdateTime } },
... { $set: { ts: lastUpdateTime, data: 123 } },
... { upsert: true, multi: false }
... );
>
> db.testcol.find()
{ "_id" : ObjectId("52310502f3bf4823f81e7fc9"), "data" : 123, "ts" : ISODate("2013-09-10T00:00:00Z") }
>
> // try one more time to check that nothing happens (due to error):
> db.testcol.update(
... {"_id" : id, "ts" : { $lt : lastUpdateTime } },
... { $set: { ts: lastUpdateTime, data: 123 } },
... { upsert: true, multi: false }
... );
E11000 duplicate key error index: test.testcol.$_id_ dup key: { : ObjectId('52310502f3bf4823f81e7fc9') }
>
> var tooOldToUpdate = ISODate("2013-09-09")
>
> // update does not happen because query condition does not match
> // and mongo tries to insert with the same id (and fails with dup again):
> db.testcol.update(
... {"_id" : id, "ts" : { $lt : tooOldToUpdate } },
... { $set: { ts: tooOldToUpdate, data: 999 } },
... { upsert: true, multi: false }
... );
E11000 duplicate key error index: test.testcol.$_id_ dup key: { : ObjectId('52310502f3bf4823f81e7fc9') }
>
> // now query cond actually matches, so update rather than insert happens which works
> // as expected:
> db.testcol.update(
... {"_id" : id, "ts" : { $lt : newUpdateTime } },
... { $set: { ts: newUpdateTime, data: 999 } },
... { upsert: true, multi: false }
... );
>
> // check that everything worked:
> db.testcol.find()
{ "_id" : ObjectId("52310502f3bf4823f81e7fc9"), "data" : 999, "ts" : ISODate("2013-09-12T00:00:00Z") }
>

唯一烦人的部分是那些错误,但它们既便宜又安全。

关于mongodb - MongoDB 中的条件更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21649146/

相关文章:

node.js - API 邮件/通知系统的正确设计模式是什么?

java - 如何在 spring-data-mongodb 中使用 mongodb 日期函数运行 mongodb native 查询?

asp.net-mvc - Entity Framework 的状态模式

java - 抽象工厂模式依赖于对象组合?

c# - 依赖注入(inject)模式下设计的基本原则是什么

javascript - Node.js:无法读取未定义的属性 'then'(嵌套查询)

mongodb - 在 Alpine 镜像上安装 MongoDB 时出现问题

node.js - 通过 mongoose 将嵌套对象结果从 MongoDB 获取到 Node 环境时出现问题

C++:当每个线程都应该同时执行 I/O 和 CPU 密集型任务时的多线程设计

java - 如何使用TestNG创建多用户测试场景?