mongodb去重

Posted clbao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mongodb去重相关的知识,希望对你有一定的参考价值。

由于某些原因,我们的MongoDB里存在重复数据,甚至已经影响到数据统计。

其实在MongoDB 3.2之前可以通过索引直接去重。但这一特性在3.2版本之初已经移除。

unique : true, dropDups : true   # 无法使用了

大概思路是,通过aggregationgroup出重复的键值对并做count,之后match所有count>2的键值对,认为他们是重复的,保留其中一条,删除其余。实现代码如下:

from pymongo import DeleteOne
from threading import Thread
from apscheduler.schedulers.blocking import BlockingScheduler
from Application.Utils.Log import Log


class DupKeywordRemove:
    def __init__(self):
        models = [monde1, monde2, monde2,
                  monde3, monde4, monde4]  # mongoengine的modle
        self.pipeline = [
            # 根据几个字段去判断键值对的唯一性,这里特别写明了"$exists": True,必须保证需要判断的字段完成,否则会影响到后面的group
            "$match": 
                "keyword": "$exists": True,
                "country_id": "$exists": True,
            ,
            # 将重复的键值对group起来,并用count计数
            "$group": 
                "_id": 
                    "keyword": "$keyword",
                    "country_id": "$country_id",
                ,
                "count": "$sum": 1
            ,
            # 匹配count大于2的键值对,他们就是重复的
            "$match": 
                "count": "$gt": 1
            
        ]
        self.main(models)

    def find_dup_id(self, model):
        try:
            _collection = model._get_collection()
            # 配置allowDiskUse=True应对mongodb的16M limit
            all_dup_key = list(_collection.aggregate(self.pipeline, allowDiskUse=True))
            delete_list = []
            # 重复的doc作为list返回,每一组键值对作为find条件去数据库里查询
            for dup_event in all_dup_key:
                match_pipe = dup_event[_id]
                remove_id_list = []
                dups = list(_collection.find(match_pipe))
                if len(dups) >= 2:
                    for key in dups:
                        remove_id_list.append(key[_id])
                    needToSave = remove_id_list.pop()  # pop一个出去,作为保留的doc
                    for to_del in remove_id_list:
                        delete_list.append(
                            DeleteOne(
                                _id: to_del
                            )
                        )
            print(_collection, len(delete_list))
            if delete_list:
                print(删除重复数据)
                _collection.bulk_write(delete_list)
            else:
                print(无重复数据)
                pass
        except Exception as e:
            Log(keyword_dup_remove).info(e)

    def main(self, models):
        t_li = []
        for _model in models:
            t_li.append(
                Thread(
                    target=self.find_dup_id,
                    kwargs=
                        model: _model,
                    
                )
            )
        for t in t_li:
            t.start()
        for t in t_li:
            t.join()


if __name__ == __main__:
    DupKeywordRemove()

参考链接:http://yangcongchufang.com/remove-duplicate-from-mongodb.html

以上是关于mongodb去重的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB distinct() 指定字段去重

MongoDB 权限备份还原去重

mongodb三种去重方式

mongodb去重的3种方式

Mongodb去除重复的数据,pymongo去重

mongodb去重操作只留一条