20

考虑一个简单的 mongo 文档结构:

{ _id,第一次,最后一次 }

客户端需要插入具有已知 ID 的文档,或更新现有文档。'lastTime' 应始终设置为最近的时间。对于“firstTime”,如果正在插入文档,则“firstTime”应设置为当前时间。但是,如果文档已经创建,则“firstTime”保持不变。我想纯粹用 upserts 来做(以避免查找)。

我已经抓取了http://www.mongodb.org/display/DOCS/Updating,但我只是不知道如何完成该特定操作。

我不认为这是不合理的,有 $push 和 $addToSet 操作可以有效地在数组字段上执行此操作,而在简单字段上没有任何操作。就像应该有类似 $setIf 操作的东西。

4

4 回答 4

33

我遇到了完全相同的问题,对于 <2.4 没有简单的解决方案,但是从 2.4 开始,$setOnInsert运算符让您可以做到这一点。

db.collection.update( <query>,
                      { $setOnInsert: { "firstTime": <TIMESTAMP> } },
                      { upsert: true }
                    )

有关详细信息,请参阅setOnInsert 的 2.4 发行说明

于 2013-04-08T06:53:39.393 回答
1

在尝试根据现有内容更新文档时,我遇到了一个非常相似的问题——也许这个解决方案也适用于你:

尝试从您的记录中删除 _id 属性并仅在更新的查询部分中使用它(您必须从 pymongo speak 翻译...)

myid = doc.get('_id')
del doc['_id']
mycollection.update({'_id':myid}, {'$set':doc}, upsert=True)
于 2013-01-31T21:51:49.290 回答
1

如果您随后将触发以下代码 2 次,它将首先在文档插入时设置firstVisitlastVisit(并将upsertedId在响应中返回),然后将仅更新lastVisit(并将返回modifiedCount: 1)。

使用 Mongo 4.0.5 进行测试,但我相信应该使用旧版本。

db.collection.updateOne(
  {_id: 1}, 
  { 
    $set: { 
      lastVisit: Date.now() 
    }, 
    $setOnInsert: {
      firstVisit: Date.now()
    }
  }, 
  { upsert: true }
);
于 2019-02-22T08:57:40.990 回答
-1

没有办法只用一个 upsert 来做到这一点。您必须将其作为 2 个操作进行 - 首先尝试插入文档,如果它已经存在,则插入将由于 _id 索引上的重复键违规而失败。然后您执行更新操作以将 lastTime 设置为现在。

于 2012-05-21T15:57:54.833 回答