mongo清理重复数据

描述

之前设置唯一索引的时候, 没有设置 unique 选项, 导致数据库中出现了重复数据。 不想 drop 掉重新拉, 就尝试了下数据的清理, 方便之后也可能会用到。

参考

链接: https://blog.csdn.net/cloume/article/details/74931998

参考了这个, 最终决定用 脚本加 命令行 手动实现。

清理脚本

	import pymongo
	import logging
	import time
	
	import pandas as pd
	
	from collections import defaultdict
	from all_codes import all
	
	
	t1 = time.time()
	
	# 默认是是列表的字典
	error_codes = defaultdict(list)
	
	error_date = set([])
	
	MongoUri = "mongodb://127.0.0.1:27017"
	db = pymongo.MongoClient(MongoUri)
	
	codes = all
	
	logger = logging.getLogger(__name__)
	
	logging.basicConfig(level=logging.DEBUG,
	                    filename='clean.log',
	                    datefmt='%Y/%m/%d %H:%M:%S',
	                    format='%(asctime)s - %(name)s - %(levelname)s - %(lineno)d - %(module)s - %(message)s')
	
	
	def convert(code):
	    if code[0] == "0" or code[0] == "3":
	        return "SZ" + code
	    elif code[0] == "6":
	        return "SH" + code
	    else:
	        pass
	
	
	for c in codes:
	
	    code = convert(c)
	
	    logger.info(code)
	
	    # 找出全部唯一的 date_int
	    dis_date_ints = db.stock.calendar.find({"code": code}).distinct("date_int")
	
	    cursor = db.stock.calendar.find({"code": code}, {"date_int": 1, "_id": 0})
	
	    all_date_ints = [r.get("date_int") for r in cursor]
	    
	    # 无需进行清理的部分
	    if sorted(dis_date_ints) == sorted(all_date_ints):
	
	        logger.info("ok")
	
	    else:
	        logger.info("no")
	
	        df = pd.DataFrame({"date": all_date_ints})
	        
	        # 使用 df 中的方法清除重复数据 
	        dup = df[df.duplicated()]
	
	        to_delete = dup["date"].tolist()
	
	        logger.info(to_delete)
	
	        error_codes[code].extend(to_delete)
	
	        error_date = error_date | set(to_delete)
	
	    t2 = time.time()
	
	
	logger.info(t2 - t1)
	
	logger.info(error_codes)
	
	logger.info(error_date)

查看日志 手动处理

主要感觉这样比较可控, 就没有直接在程序中删除 。

mongo清理重复数据_第1张图片

比如以上,就说明是 SH600136 这只股票在 20180708 的数据有重复。

找到非 SH000001 的部分进行清理:

db.calendar.find({"date_int": 20190527, "code": {$ne: "SH000001"}}).count()

删除多个重复的数据中的一个, (在查出有两个数据的时候适用)

db.calendar.remove({"code": "SH600136", "date_int":20180708}, {"justOne": true})

在清理过后尝试设置惟一的联合索引值:

db.justtest.ensureIndex({"code": 1, "date_int": 1}, {unique: true})

在已经有数据的集合中尝试建立唯一索引,还是有重复值的话就会报错:

"errmsg" : "{ rs1/Lianghua_HW_GZ_124:27101,Lianghua_HW_GZ_152:27101,Lianghua_HW_GZ_163:27101:
\"Index with name: code_1_date_int_1 already exists with different options\" }"

更新:20190601
我们需要删除之前的索引才可以插入新的 不删除原来的同名索引的时候, 会报错:

	"errmsg" : "{ rs1/Lianghua_HW_GZ_124:27101,Lianghua_HW_GZ_152:27101,Lianghua_HW_GZ_163:27101: " \
	           "\"Index with name: code_1_date_int_1 already exists with different options\" }"
	db.calendar.dropIndex("code_1_date_int_1")

删除索引的命令:

db.calendar.dropIndex("code_1_date_int_1")

更新于: 2019.6.19
在mongo shell 命令行中查看数据库的索引: getIndexes()
mongo清理重复数据_第2张图片
在 date和 index之间建立唯一索引:
mongo清理重复数据_第3张图片
db.generate_indexcomponentsweight.ensureIndex({“date”: 1, “index”: 1}, {unique: true})
mongo清理重复数据_第4张图片
再次查看:
mongo清理重复数据_第5张图片

你可能感兴趣的:(数据库)