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

PyMongo设置复合索引后仍出现重复气象数据 如何彻底避免?

问题根因分析
  1. 索引创建语法错误:pymongo 创建复合索引需传入由(字段名, 排序规则)组成的列表,你当前的传参方式错误,并未生成预期的三字段复合索引。
  2. 未添加唯一约束:默认创建的索引仅用于查询加速,只有添加unique=True参数才会触发字段唯一性校验,重复数据写入时会抛出异常拒绝写入。
  3. 可能存在的字段不匹配问题:需确认索引声明的unity、id_sensor、date_time三个字段,和实际存入MongoDB的字段名、字段格式完全一致,比如date_time如果存在字符串格式和日期对象混合存储的情况,也会导致唯一性校验失效。
  4. 脚本并发执行:crontab 每15分钟触发一次脚本,如果前一次脚本因接口响应慢、数据处理耗时久未执行完成,后一次脚本启动后会同时写入数据,在索引未生效的场景下极易产生重复。
解决方案
  • 第一步:修正唯一复合索引的创建逻辑
    正确的pymongo创建三字段唯一复合索引代码如下:

    collection.create_index(
        [
            ("unity", pymongo.ASCENDING),
            ("id_sensor", pymongo.ASCENDING),
            ("date_time", pymongo.ASCENDING)
        ],
        unique=True
    )
    

    创建完成后可在MongoDB shell执行db.你的集合名.getIndexes()确认索引存在且unique属性为true。注意创建索引前需先删除集合中已有的重复数据,否则索引会创建失败。

  • 第二步:写入数据时使用upsert逻辑替代直接插入
    不要直接调用insert_one/insert_many写入数据,改用update_one的upsert模式,基于三个唯一字段做匹配,存在则跳过/更新,不存在则写入,示例代码如下:

    collection.update_one(
        {
            "unity": 你的单位值,
            "id_sensor": 传感器ID,
            "date_time": 数据时间
        },
        {"$setOnInsert": 你的完整数据字典},
        upsert=True
    )
    

    $setOnInsert操作符只会在文档不存在、触发插入操作时写入字段,文档已存在时不会做任何修改,不会影响原有数据。

  • 第三步:新增脚本运行互斥锁,避免并发执行
    给crontab任务添加flock锁,确保同一时间只有一个脚本进程在运行,示例crontab配置如下:

    */15 * * * * /usr/bin/flock -n /tmp/meteorology_script.lock /usr/bin/python3 你的脚本路径.py
    

    其中-n参数表示获取不到锁时直接退出,避免任务堆叠。

  • 第四步:拉取数据后先做前置去重
    接口返回全量历史数据后,先按三个唯一字段对本次拉取的数据集做本地去重,避免同批次拉取的数据本身存在重复,再执行写入操作。

内容的提问来源于stack exchange,提问作者Giuseppe Ricci

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 15:09:03