【问题标题】:mongodb: upserting: only set value if document is being insertedmongodb:upserting:仅在插入文档时设置值
【发布时间】:2019-02-22 16:57:40
【问题描述】:

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

{ _id, firstTime, lastTime }

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

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

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

【问题讨论】:

  • 如果文档已经创建,该字段应保持不变它不称为 upsert(如您的标题)
  • @om-nom-nom 我已经概述了最简单的情况,我已经更新了描述,所以有一个字段一直在更新。
  • 看起来这个功能是针对 2.4 的:jira.mongodb.org/browse/SERVER-340

标签: mongodb


【解决方案1】:

我遇到了完全相同的问题,对于 $setOnInsert 运算符让您可以做到这一点。

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

请参阅2.4 release notes of setOnInsert 了解更多信息。

【讨论】:

    【解决方案2】:

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

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

    myid = doc.get('_id')
    del doc['_id']
    mycollection.update({'_id':myid}, {'$set':doc}, upsert=True)
    

    【讨论】:

      【解决方案3】:

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

      使用 Mongo 4.0.5 进行测试,但我认为应该可以使用旧版本。

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

        • 恕我直言,这将破坏目的,做和等待,第一个操作相当于同步查找。我没有看到“尝试失败”和查找和更新的区别......
        • 多个并发写入者的查找、更新和更新方法存在竞争条件。如果另一个写入者进来并在第一个线程进行读取和写入之间创建/更改文档,您可能会覆盖另一个线程所做的写入。
        • 这就是为什么我希望它在单个 write() 操作中,所以要求 Mongo 以原子方式执行它。
        猜你喜欢
        • 2017-07-10
        • 2019-06-03
        • 2020-07-03
        • 2019-10-16
        • 2022-11-28
        • 2018-06-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多