PyMongo设置复合索引后仍出现重复气象数据 如何彻底避免?
问题根因分析
- 索引创建语法错误:pymongo 创建复合索引需传入由
(字段名, 排序规则)组成的列表,你当前的传参方式错误,并未生成预期的三字段复合索引。 - 未添加唯一约束:默认创建的索引仅用于查询加速,只有添加
unique=True参数才会触发字段唯一性校验,重复数据写入时会抛出异常拒绝写入。 - 可能存在的字段不匹配问题:需确认索引声明的
unity、id_sensor、date_time三个字段,和实际存入MongoDB的字段名、字段格式完全一致,比如date_time如果存在字符串格式和日期对象混合存储的情况,也会导致唯一性校验失效。 - 脚本并发执行: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
相关产品推荐
相关产品推荐

