mongodb:upserting:仅在插入文档时设置值

时间:2012-05-20 07:43:17

标签: mongodb

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

{_ id,firstTime,lastTime}

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

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

我不相信这是不合理的,有$ push和$ addToSet操作可以在数组字段上有效地执行此操作,只是在简单字段上没有任何相同的操作。这就像应该有$ setIf操作。

4 个答案:

答案 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)

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

尽管我认为应该在较旧的版本上使用Mongo 4.0.5进行测试。

db.collection.updateOne(
  {_id: 1}, 
  { 
    $set: { 
      lastVisit: Date.now() 
    }, 
    $setOnInsert: {
      firstVisit: Date.now()
    }
  }, 
  { upsert: true }
);