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

使用pymongo操作MongoDB嵌套文档 实现城市数组全量覆盖更新问题

问题解决方案

错误原因说明

  1. 原有步骤2的$addToSet逻辑缺陷:$addToSet判断数组元素是否重复的依据是整个对象完全一致,首次插入国家后该对象会新增cities字段,后续再传入仅包含country_id和country_name的对象时,$addToSet会判定为新对象,导致重复插入同id的国家。
  2. 原有第三步的写法直接对countries根级数组赋值,会覆盖整个数组的所有内容,自然丢失其他国家的信息。

实现方案

方案1:兼容性写法(支持所有MongoDB版本)

分两步操作,逻辑清晰无歧义:

  1. 先确保大洲文档存在,仅插入新文档时赋值,不会覆盖已有数据
continents.update_one(
    {"continent_id": CONTINENT_ID},
    {"$setOnInsert": {"continent_name": CONTINENT_NAME, "countries": []}},
    upsert=True
)
  1. 原子更新国家城市数据:先尝试覆盖已有国家的城市数组,匹配不到则新增带城市的国家条目
# 尝试更新已有国家的城市数组
update_result = continents.update_one(
    {
        "continent_id": CONTINENT_ID,
        "countries.country_id": COUNTRY_ID
    },
    {
        "$set": {
            "countries.$[country].cities": [{"city_id": city["city_id"], "city_name": city["city_name"]} for city in CITIES]
        }
    },
    array_filters=[{"country.country_id": COUNTRY_ID}]
)

# 没有匹配到说明国家不存在,直接追加新国家+城市数据
if update_result.matched_count == 0:
    continents.update_one(
        {"continent_id": CONTINENT_ID},
        {
            "$push": {
                "countries": {
                    "country_id": COUNTRY_ID,
                    "country_name": COUNTRY_NAME,
                    "cities": [{"city_id": city["city_id"], "city_name": city["city_name"]} for city in CITIES]
                }
            }
        }
    )

方案2:单语句管道写法(MongoDB 4.2+支持)

用更新管道单条语句完成所有逻辑,无需判断返回结果:

continents.update_one(
    {"continent_id": CONTINENT_ID},
    [
        # 过滤掉countries数组中当前国家的旧数据
        {
            "$set": {
                "countries": {
                    "$filter": {
                        "input": "$countries",
                        "cond": {"$ne": ["$$this.country_id", COUNTRY_ID]}
                    }
                }
            }
        },
        # 插入当前国家的最新全量数据
        {
            "$push": {
                "countries": {
                    "country_id": COUNTRY_ID,
                    "country_name": COUNTRY_NAME,
                    "cities": [{"city_id": city["city_id"], "city_name": city["city_name"]} for city in CITIES]
                }
            }
        }
    ],
    upsert=True
)

两种方案都完全符合需求:国家不存在时新增带城市数组的条目,国家存在时全量覆盖原有城市数组,不会保留旧数据,也不会出现重复国家的问题。

内容的提问来源于stack exchange,提问作者Jake Ratcliffe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 03:09:00