mongodb: upserting: only set value if document is being inserted

后端 未结 4 746
不知归路
不知归路 2021-01-03 22:12

Considering a simple mongo document structure:

{ _id, firstTime, lastTime }

The client needs to insert a document with a known ID, or update an existing docu

相关标签:
4条回答
  • 2021-01-03 22:18

    If you will trigger the following code 2 subsequent times, it will first set both firstVisit and lastVisit on document insert (and will return upsertedId in the response) and on the second it will only update lastVisit (and will return modifiedCount: 1).

    Tested with Mongo 4.0.5 though I believe should be working with older versions.

    db.collection.updateOne(
      {_id: 1}, 
      { 
        $set: { 
          lastVisit: Date.now() 
        }, 
        $setOnInsert: {
          firstVisit: Date.now()
        }
      }, 
      { upsert: true }
    );
    
    0 讨论(0)
  • 2021-01-03 22:21

    I ran into a very similar problem when attempting to upsert documents based on existing content--maybe this solution will work for you also:

    Try removing the _id attribute from your record and only use it in the query portion of your update (you'll have to translate from pymongo speak...)

    myid = doc.get('_id')
    del doc['_id']
    mycollection.update({'_id':myid}, {'$set':doc}, upsert=True)
    
    0 讨论(0)
  • 2021-01-03 22:29

    There's no way to do this with just one upsert. You'd have to do it as 2 operations - first try to insert the document, if it already exists the insert will fail due to duplicate key violation on the _id index. Then you do an update operation to set the lastTime to now.

    0 讨论(0)
  • 2021-01-03 22:31

    I ran into the exact same problem and there was no simple solution for <2.4 however since 2.4 the $setOnInsert operator let's you do exactly that.

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

    See the 2.4 release notes of setOnInsert for more info.

    0 讨论(0)
提交回复
热议问题