考虑一个简单的mongo文档结构:
{_ id,firstTime,lastTime}
客户端需要插入具有已知ID的文档,或更新现有文档。 'lastTime'应始终设置为某个最新时间。对于'firstTime',如果正在插入文档,则应将'firstTime'设置为当前时间。但是,如果已创建文档,则“firstTime”保持不变。我想纯粹用upserts做这件事(为了避免仰视)。
我已经抓取了http://www.mongodb.org/display/DOCS/Updating,但我只是看不出该特定操作是如何完成的。
我不相信这是不合理的,有$ push和$ addToSet操作可以在数组字段上有效地执行此操作,只是在简单字段上没有任何相同的操作。这就像应该有$ setIf操作。
答案 0 :(得分:28)
我遇到了完全相同的问题,并且没有针对< 2.4的简单解决方案,但是因为2.4 $ setOnInsert 运算符让你做到了这一点。
db.collection.update( <query>,
{ $setOnInsert: { "firstTime": <TIMESTAMP> } },
{ upsert: true }
)
有关详细信息,请参阅2.4 release notes of setOnInsert。
答案 1 :(得分:1)
在尝试根据现有内容插入文档时遇到了类似的问题 - 也许这个解决方案对您也有用:
尝试从您的记录中删除_id属性,并仅在更新的查询部分中使用它(您必须从pymongo翻译说...)
myid = doc.get('_id')
del doc['_id']
mycollection.update({'_id':myid}, {'$set':doc}, upsert=True)
答案 2 :(得分:0)
只用一次upsert就无法做到这一点。你必须做2次操作 - 首先尝试插入文档,如果它已经存在,插入将因为_id索引上的重复键违规而失败。然后执行更新操作以将lastTime设置为现在。
答案 3 :(得分:0)
如果您随后两次触发以下代码,它将首先在插入文档时设置firstVisit
和lastVisit
(并在响应中返回upsertedId
),然后在第二次设置只会更新lastVisit
(并返回modifiedCount: 1
)。
尽管我认为应该在较旧的版本上使用Mongo 4.0.5进行测试。
db.collection.updateOne(
{_id: 1},
{
$set: {
lastVisit: Date.now()
},
$setOnInsert: {
firstVisit: Date.now()
}
},
{ upsert: true }
);