You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用flask_pymongo执行upsert操作时如何获取对应文档ID?

问题根因

flask-pymongo 是对pymongo的轻量封装,你调用的update_one方法返回的UpdateResult对象本身就仅在upsert触发新文档插入时,才会携带upserted_id属性;如果是命中已有文档执行更新,返回结果默认不包含文档_id,这是pymongo的标准设计。

可行解决方案

方案1:基于现有update_one逻辑补充查询(仅适合低并发场景)

先判断upsert行为是插入还是更新,更新场景下补充一次查询拿_id:

a = mongo.db.abcd.update_one(
    {'abcd': 'abcd1'}, {"$set": {"abcd": "abcd2"}}, upsert=True
)

target_id = None
# 新插入场景直接取返回的id
if a.upserted_id is not None:
    target_id = a.upserted_id
# 更新场景通过查询条件拿已有文档的id
else:
    doc = mongo.db.abcd.find_one({"abcd": "abcd2"}, {"_id": 1})
    if doc:
        target_id = doc["_id"]

print(target_id)

该方案存在并发风险:如果update_one执行后、find_one执行前有其他请求修改了匹配的文档,可能拿到错误的_id。

方案2:使用find_one_and_update(推荐,原子操作)

直接用pymongo提供的原子操作方法find_one_and_update,执行upsert的同时直接返回文档内容,不管是插入还是更新都能直接拿到_id:

from pymongo import ReturnDocument

doc = mongo.db.abcd.find_one_and_update(
    {'abcd': 'abcd1'},
    {"$set": {"abcd": "abcd2"}},
    upsert=True,
    # 配置返回更新后的文档
    return_document=ReturnDocument.AFTER
)

target_id = doc["_id"]
print(target_id)

该方案全程为原子操作,不存在并发冲突问题,是生产环境的最优选择。


内容的提问来源于stack exchange,提问作者Tlaloc-ES

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 05:06:03