如何在PyMongo中执行带upsert=true的Update后获取记录的my_id
解决MongoDB Upsert后获取my_id的问题
嘿,我明白你的需求了——你想在执行upsert操作时,不管是插入了新记录还是命中了已存在的记录,都能拿到对应的my_id。原来的update方法返回的只是操作状态,所以你直接取status['my_id']肯定会报错,我给你两种解决方案,推荐第一种更高效的方式:
推荐方案:使用find_one_and_update(原子操作,一次搞定)
find_one_and_update是pymongo里更适合这种场景的方法,它可以在执行upsert的同时,直接返回操作后的文档(不管是新插入的还是已存在的)。
修改后的代码示例:
import pymongo from pymongo import ReturnDocument client = pymongo.MongoClient(settings.MONGO_DB_URI) db = client[settings.MONGO_DB_NAME] # 定义匹配条件 filter_query = {'my_id': '1234', 'name': 'alok'} # 定义要插入的新记录内容 record_to_insert = {'my_id': '1234', 'name': 'alok', 'marks': 26} # 执行upsert并返回操作后的文档 result_doc = db['mycollection'].find_one_and_update( filter_query, {'$setOnInsert': record_to_insert}, upsert=True, return_document=ReturnDocument.AFTER # 指定返回操作后的最新文档 ) # 直接从返回的文档中获取my_id print('id is ', result_doc['my_id'])
为什么这个方法好用:
- 它是原子操作:一次完成“查找匹配记录→不存在则插入→返回目标文档”的流程,避免了多步操作可能带来的并发问题。
ReturnDocument.AFTER确保你拿到的是最终状态的文档:如果是插入新记录,返回的就是刚插入的文档;如果是命中已有记录,返回的就是原有的匹配文档,两种情况都能直接拿到my_id。
备选方案:基于update结果二次查询(不推荐,效率低)
如果你坚持想用update方法,也可以通过返回的状态判断是插入还是已存在,再去查询对应的文档,但这种方式需要额外的查询操作,效率不如第一种:
代码示例:
import pymongo client = pymongo.MongoClient(settings.MONGO_DB_URI) db = client[settings.MONGO_DB_NAME] filter_query = {'my_id': '1234', 'name': 'alok'} record_to_insert = {'my_id': '1234', 'name': 'alok', 'marks': 26} status = db['mycollection'].update(filter_query, {'$setOnInsert': record_to_insert}, upsert=True) if status.get('upserted'): # 说明插入了新记录,通过upserted的_id去查询文档 inserted_doc = db['mycollection'].find_one({'_id': status['upserted']}) print('id is ', inserted_doc['my_id']) else: # 说明记录已存在,直接用原filter查询 existing_doc = db['mycollection'].find_one(filter_query) print('id is ', existing_doc['my_id'])
注意点:
这种方式在高并发场景下可能出现问题——比如在update和find_one之间,数据可能被其他操作修改,所以更推荐第一种原子操作的方案。
内容的提问来源于stack exchange,提问作者Alok
相关产品推荐
相关产品推荐

