MongoDB mapReduce填补自带group的限制问题

【信息科学与工程学】【数据科学】数据科学领域-第十一篇 数据集成算法01 ​​降低维护成本​​:通过抽象通用流程(如),当需要修改故障注入逻辑(如更换混沌工具)时,只需修改一处代码,无需修改所有测试用例;​​提升扩展性​​:通过参数化故障场景(如),可快速生成新的故障用例(如针对新服务的延迟故障),适应系统迭代需求;​​增强场景真实性​​:通过组合混沌操作(如),模拟真实生产环境中的复杂故障链(如“网络延迟+服务宕机”),更准确地验证系统韧性;​​提高分析效率​​:通过自动化结果分析(如),快速获取MTTR、错误率等关键指标,减少人工分析时间。 阅读详情

用过MongoDB的小伙伴或多或少都会遇到MongoDB自带group的限制问题,即group不支持大于2万的结果集!

我曾在任职公司做过某网站小区均价数据抓取,采用的是Groovy技术。数据抓取下来后存放在MongoDB中。数据抓取完成都是需要经历数据清洗处理的,其中有一项数据去重时候就遇到MongoDB自带group的限制问题,即group不支持大于2万的结果集。几番折腾后来采用MongoDB mapReduce来处理。

下面是数据去重的部分核心代码,已做脱敏处理!

package com.script.thirdPriceCrawl

import com.script.util.MongoUtils
import com.mongodb.BasicDBObject
import com.mongodb.DB
import com.mongodb.DBCollection
import com.mongodb.DBObject
import com.mongodb.MapReduceOutput
import org.apache.commons.lang.StringUtils

import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit

/**
 * 网络爬虫:
 * 某网站-小区均价数据抓取<br>
 * http://www.xxx.com/
 * 
 * 解析完成后通过MapReduce统计/清理重复数据工具类<br>
 * 在清洗数据脚本执行之前调用
 *
 * @author 小辉哥/小辉GE
 * 2019年9月5日 下午21:22:12
 *
 */
class ThirdPartPriceDataRepeatBatchUtils {
    //MapReduce 执行分组后输出DBCollection
    def static final THIRD_PARTY_PRICE_DATAREPEAT_TEMP = "third_party_price_repeat_data_temp"
    def static final THIRD_PARTY_PRICE_DATAPRICEREPEAT_TEMP = "third_party_price_repeat_dataprice_temp"
    //线程池
    def static ExecutorService fixedThreadPoolQuery
    //其他变量
    def static final CONNECT_CHAR = "#####"

    /**
     * 每次执行时候初始化线程池, 防止类已加载就要多个线程池中线程占用内存
     * @param type
     * @return
     */
    def static initThreadPool(){
        fixedThreadPoolQuery = Executors.newFixedThreadPool(50)
    }

    /**
     * 全量测试执行时间为277分钟, 预计执行时间为五小时
     * 
     * 返回当月总解析后重复数据
     * 判断分组标准:s_date+source+city+region+name
     * 备注:方法在解析完成清洗开始前执行
     * @param sdate
     * @param thirdPartyColl
     * @return
     */
    def static findThirdPriceDataRepeatBatch(sdate, DBCollection thirdPartyColl){
        try {
            println("findThirdPriceDataRepeatBatch 处理重复数据开始")
            long start = System.currentTimeMillis()
            //query条件, 按sdate筛选
            DBObject query = new BasicDBObject().append("s_date", sdate)
            //mapfun
            String mapfun =
                    "function(){" +
                        "emit({s_date:this.s_date, source:this.source, city:this.city, region:this.region, name:this.name}, 1);" +
                    "};"
            //reducefun
            String reducefun =
                    "function(key, values){" +
                        "return values.length;" +
                    "};"
            //执行MapReduce
            MapReduceOutput mapReduce = thirdPartyColl.mapReduce(mapfun, reducefun, THIRD_PARTY_PRICE_DATAREPEAT_TEMP, query)
            if(mapReduce!=null && mapReduce.results().size()>0){
                //初始化线程池(初始化放在mapReduce.results()结果后, 保证thirdPartyColl.mapReduce发生异常, 线程池未创建)
                initThreadPool()
                mapReduce.results().each { DBObject o ->
                    try{
                        if(o.value > 1) {
                            fixedThreadPoolQuery.execute(
                                new Runnable() {
                                    void run() {
                                        try {
                                            println("调用findThirdPriceDataRepeatByPriceBatch, 传入的obj对象为: "+o.toString())
                                            findThirdPriceDataRepeatByPriceBatch((int)(o._id.s_date), o._id.source, o._id.city, o._id.region, o._id.name, thirdPartyColl)
                                        } catch (Exception e) {
                                            println "调用findThirdPriceDataRepeatByPriceBatch -> DBObject对象为"+o.toString()+"发生异常, 异常信息为:" + e.getMessage()
                                        } finally {

                                        }
                                    }
                                }
                            )
                        }
                    } catch (Exception e) {
                        println("findThirdPriceDataRepeat --> mapReduce.results().each { DBObject o -> DBObject对象为"+o.toString()+", 时发生异常, 异常信息为" + e.getLocalizedMessage())
                    }
                }
                fixedThreadPoolQuery.shutdown()
                fixedThreadPoolQuery.awaitTermination(2, TimeUnit.DAYS)
                long end = System.currentTimeMillis()
                println "findThirdPriceDataRepeatBatch 处理重复数据完成,耗时:" + (end - start)
            }
        } catch (Exception e) {
            println("findThirdPriceDataRepeatBatch(sdate, DBCollection thirdPartyColl){发生异常, 异常信息为" + e.getLocalizedMessage())
        }
    }

    /**
     * 判断分组标准:s_date+source+city+region+name+avg_price
     * @param sdate
     * @param source
     * @param city
     * @param region
     * @param name
     * @param thirdPartyColl
     * @return
     */
    def static findThirdPriceDataRepeatByPriceBatch(sdate, source, city, region, name, DBCollection thirdPartyColl){
        //按价格分组后, 判断是否出现多次不同的价格, 并不是根据分组的count判断,
        //而是根据按照价格分组后, 对应sdate+source+city+region+name 还出现多次在mapReduce.results()中, 即为重复数据
        def dataRepeatMap = [:]
        try{
            //query条件, 按sdate筛选
            DBObject query = new BasicDBObject().append("s_date", sdate)
                    .append("source",source).append("city", city).append("region", region).append("name", name)
            //mapfun
            String mapfun =
                    "function(){" +
                        "emit({s_date:this.s_date, source:this.source, city:this.city, region:this.region, name:this.name, avg_price:this.avg_price}, 1);" +
                    "};"
            //reducefun
            String reducefun =
                    "function(key, values){" +
                        "return values.length;" +
                    "};"
            //执行MapReduce
            MapReduceOutput mapReduce = thirdPartyColl.mapReduce(mapfun, reducefun, THIRD_PARTY_PRICE_DATAPRICEREPEAT_TEMP, query)
            if(mapReduce!=null && mapReduce.results().size()>0){
                mapReduce.results().each { DBObject o ->
                    try{
                        def sd = (int) o._id.s_date
                        def keys = sd + CONNECT_CHAR + o._id.source + CONNECT_CHAR + o._id.city + CONNECT_CHAR + o._id.region + CONNECT_CHAR +  o._id.name
                        if (!dataRepeatMap.containsKey(keys)) {
                            println("dataRepeatMap 中不含有 keys:" + keys + "加入dataRepeatMap")
                            dataRepeatMap.put(keys, keys)
                        } else {
                            println("dataRepeatMap 中含有 keys:" + keys + "执行删除方法, 对象为: " + o.toString())
                            deleteThirdPriceDataBatch((int) (o._id.s_date), o._id.source, o._id.city, o._id.region, o._id.name, thirdPartyColl)
                        }
                    } catch (Exception e) {
                        println("调用deleteThirdPriceDataBatch DBObject对象为"+o.toString()+", 时发生异常, 异常信息为" + e.getLocalizedMessage())
                    }
                }
            }
        }catch (Exception e) {
            println("findThirdPriceDataRepeatByPriceBatch(sdate, source, city, region, name, DBCollection thirdPartyColl){发生异常, 异常信息为" + e.getLocalizedMessage())
        }
    }

    /**
     * 删除重复数据
     * @param sdate
     * @param source
     * @param city
     * @param region
     * @param name
     * @param thirdPartyColl
     */
    def static deleteThirdPriceDataBatch(sdate, source, city, region, name, DBCollection thirdPartyColl){
        DBObject obj = new BasicDBObject();
        obj.put("s_date", sdate)
        obj.put("source", source)
        obj.put("city", city)
        obj.put("region", region)
        obj.put("name", name)
        thirdPartyColl.remove(obj);
    }

}

输出结果在这里就不展示了!!!

以上代码仅供参考,如有不当之处,欢迎指出!!!

更多干货,欢迎大家关注和联系我。期待和大家一起更好的交流、探讨技术!!!

 

 

学习MongoDB 十: MongoDB聚合(Map-Reduce)(二) MapReduce要实现两个函数:Map和Reduce。Map函数调用emit(key,value)遍历一个或多个集合中所有的记录,进行分组(group by),然后将key与value传给Reduce函数进行处理,输出结果。 (1)MapReduce使用自定义JavaScript函数执行map和reduce操作,所以是基于js引擎,单线程执行,效率不高,比Aggregation复杂,适合用做后台统计等。 (2)MapReduce支持分片操作,可以进行 阅读详情

相关推荐

MongoDB 聚合Group(一)

db.collection.group()使用JavaScript,它受到了一些性能上的限制。大多数情况下,$ group在Aggregation Pipeline提供了一种具有较少的限制适用的替代。可以通过指定的键的集合中的文档和执行简单的聚合函数。在2.2版本中,返回的数组可以包含最多20000个元素;即最多20000个独特的分组。 我们比较熟悉的group by 的sql语句select key from table groupby key,而mongoDB没提供SQL那样通过Group B

在前进的路上 3万+

MongoDB 统计 group 操作用不了,试试 mapReduce 吧

问题回顾今天,同事小张 Q 我, 说自己辛苦花了一天的时间,基于mongodb数据库开发的待办统计功能一直报错!于是笔者花了近半小时了解小张的开发需求以及代码实现方式,大致明白问题出...

916

mongo group by mapreduce操作

mongo group by mapreduce操作指导!

mongoDB--mapreduce用法详解(经典)

Map-Reduce部分:Map-Reduce相当于关系型数据库中的group by,主要用于统计数据之用。 先引入一个问题: 在MongoDB javascript Shell中对Array对象进行了一些扩展,其中新增sum方法,以方便统计数据之用的。 >Array.sum function(arr){ if(arr.length == 0) return null; var

GP的空间 1万+

MongoDB中MapReduce的使用方法详解

前言 玩过Hadoop的小伙伴对MapReduce应该不陌生,MapReduce的强大且灵活,它可以将一个大问题拆分为多个小问题,将各个小问题发送到不同的机器上去处理,所有的机器都完成计算后,再将计算结果合并为一个完整的解决方案,这就是所谓的分布式计算。本文我们就来看看MongoDB中MapReduce的使用。 打算用mongodb mapreduce之前一定要知道的事!!! mapreduce其实是分批处理数据的,每一百次重新reduce处理,所以到reduce里的数据如果是101条,那就会分2次进入。 这导致的问题就是在reduce中 如果 初始化 var count = 0;在循环中 c

叶绿体基因组提交NCBI全流程避坑指南

叶绿体基因组作为环状细胞器DNA,其数据提交并非简单上传,而是需严格遵循INSDC标准的学术出版行为。其核心原理在于元数据完整性、拓扑结构语义一致性与分类学路径精确匹配;技术价值体现在保障序列可追溯、可复现、可互操作;典型应用场景涵盖植物系统发育、条形码开发及合成生物学底盘构建。实践中,FASTA头行格式、feature table嵌套规则、taxid绑定及BankIt静默校验等环节极易引发失败。本文聚焦NCBI|叶绿体基因组数据上传中的高频报错与隐性约束,提供面向生物信息工程师的实操级规范解析。

weixin_31960565的博客 321

MongoDB 数据库操作(五)—MapReduce(groupBy)

1. MongoDB 的MapReduce 相当于Mysql 中的"group by",所以在MongoDB 上使用 Map/Reduce进行并行"统计"很容易。使用MapReduce 要实现两个函数 Map 函数和Reduce 函数,Map 函数调用emit(key, value),遍历collection中所有的记录,将key与value传递给Reduce 函数进行处理。Map函数和Reduc

Silver_sail的专栏 3763

【深度学习】通俗易懂讲解循环神经网络LSTM

目录 1、循环神经网络(Recurrent Neural Networks) 2、长依赖存在的问题 3、LSTM 网络 4、LSTMs的核心思想 5、一步一步理解LSTM 6、LSTM的变种 7、总结 1、循环神经网络(Recurrent Neural Networks) 人对一个问题的思考不会完全从头开始。比如你在阅读本片文章的时,你会根据之前理解过的信息来理解下面看到的文字。...

Nieson2012的专栏 2728

mongo java mapreduce_MongoDB聚合比较:group(),$ group和MapReduce

group()命令,Aggregation Framework和MapReduce是MongoDB的统一聚合功能 . 功能有一些重叠,但我会尝试解释MongoDB 2.2.0中每个功能的差异和限制 .注意:下面提到的内联结果集指的是在内存中处理的查询以及在函数调用结束时返回的结果 . 替代输出选项(目前仅适用于MapReduce)可以包括将结果保存到新的或现有的集合 .group()命令用于分组的...

weixin_30412847的博客 584

NE5532A与JRC4580在低噪声音频电路设计中的关键应用

本文深入探讨了经典运算放大器NE5532A与JRC4580在低噪声音频电路设计中的核心应用。文章从噪声模型分析入手,阐述了针对低阻抗信号源时,如何利用这两款BJT输入运放的低电流噪声特性进行优化设计。通过对比两者参数与实战守则,为设计高保真音频前级、耳机放大等电路提供了从原理图到PCB布局的完整低噪声解决方案。

weixin_29295541的博客 327

本体(Ontology)概述

认识本体        本体(Ontology)的概念源自于哲学领域,在哲学中的定义为“对世界上客观事物的系统描述,即存在论”。哲学中的本体关心的是客观现实的抽象本质。而在计算机领域,本体可以在语义层次上描述知识,可以看成描述某个学科领域知识的一个通用概念模型。德国学者Studer在1998年给出了本体的相关定义“本体是共享概念模型的形式化规范说明”。这个定义包含了四层含义:即共享(share)...

baijinswpu的博客 7万+

MongoDB mapReduce使用

转载自:http://blog.youkuaiyun.com/qqiabc521/article/details/6330783 MongoDB的MapReduce相当于Mysql中的group使用MapReduce要实现两个函数 Map Function 和 Reduce Function 在调用mapReduce时需要用到这两个函数db.things.mapReduce(Map Function, Re

郭小郭的专栏 4404

零、HarmonyOS应用开发者基础学习总览

零、HarmonyOS应用开发者基础学习总览

weixin_45029825的博客 1453

MongoDB聚合管道:数据流流水线设计与实战避坑指南

聚合管道是MongoDB中对原始文档进行结构化处理的核心机制,其本质并非高级查询语法,而是基于阶段化数据流的声明式计算模型。它遵循输入→过滤→变形→分组→输出的工程化流程,依托$match、$group、$sort等阶段协同完成实时统计、多维分析与关联计算。相比应用层处理,聚合能显著降低网络传输、内存占用与响应延迟,尤其适用于用户行为分析、订单报表、实时看板等高并发场景。本文结合电商订单分析实例,深入解析流水线思维、嵌套数组展开、$lookup关联优化及$facet多维聚合等关键技术要点。

dianchaozong3657的博客 383

基于PChmi.dll的PLC报警显示和记录(C#)

本文介绍了如何使用C#编写基于PChmi.dll的程序,实现PLC报警的显示和记录功能。通过订阅PLC的报警事件,我们可以实时显示报警信息,并通过日志文件记录报警历史。PLC(可编程逻辑控制器)在工业自动化领域中扮演着重要的角色,而报警显示和记录是PLC应用中常见的需求。本文将介绍如何使用C#编写基于PChmi.dll的程序,实现PLC报警的显示和记录功能。当然,这只是实现报警显示和记录的基本框架,具体的实现方式可能因不同的PLC和HMI库而有所差异。你需要根据你所使用的具体库和设备进行相应的调整和修改。

ByteLegend的博客 1670

【BlueDroid】【BLE】低功耗蓝牙客户端和服务端开发流程解析(超详细)

1. 精讲):SPP/A2DP/AVRCP/HFP/PBAP/IAP2/HID/MAP/OPP/PAN/GATTC/GATTS/HOGP等协议理论2. 欢迎大家关注和订阅,和专栏会持续更新中.....敬请期待!

风云说通信 1924

MongoDB MapReduce实现的group问题

用MapReduce写的group速度不行啊!!1)来源MongoDB权威指南 The price of using MapReduce is speed: group is not particularly speedy, but MapReduce is slower and is not supposed to be used in “real time.” You run MapReduce as a background job, it creates a collection of res

Mac Track 4856

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

MongoDB4:聚合函数group和mapReduce

我们可以使用group或mapReduce来实现分组和统计的功能,参考:https://docs.mongodb.com/manual/reference/method/db.collection.group/1.group测试:db.order.insert({id:123,mount:500}) yooo:PRIMARY&gt; db.order.find() { "_id" : Object...

aryoyo的博客 1538

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

mongodb分片集合不支持group操作解决之mapreduce的使用

首先说一下分片: 分片(sharding)是指将数据拆分,将其分散存放在不同的机器上的过程。有时也用分区(partitioning)来表示这个概念。将数据分散到不同的机器上,不需要功能强大的大型计算机就可以存储更多的数据,处理更大的负载。 这里不讲怎么操作分片有兴趣自己百度   那么分片之后的集合是不支持group操作的 会报错,为解决这个问题 使用map reduce操作 首先上个简单...

zhang_zhongkang的博客 1450

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

mongodb的mapreduce的分组统计

m = function (){ emit(this.hs,{customid_count:this.customid,salescountry_count:salescountry,usd_sum:this.usd,num_sum:this.num,compid_count:compid}); } r=function (key,values){ var custom= {};

一天一点点的专栏 4270

MongoDB GroupBy操作, 结果集大小限制问题。

为什么80%的码农都做不了架构师?>>> ...

weixin_33708432的博客 1091

mongo数据库 mapreduce 与 group 效率比较

参考: http://www.oecp.cn/hi/yongtree/blog/2001 http://www.360doc.com/content/11/0517/07/2660674_117324396.shtml http://www.360doc.com/content/11/0906/16/1542811_146231902.shtml   与传统的关系型数据库一样,mongo

shuzui1985的专栏 3745

spring mongo 下 mapreduce 和 group的用法

1.  KeywordsStaticsModel   数据模型 private String id; private String keyword; //关键词 private String keywordUuid;//keyword + datestr 的md5 //搜索相关 private int sessionCount = 0; private int adsCount =

kindy的开发工作室 2319

mongodb group分组个数过滤

db.books.aggregate([ { $group : { _id : {name:"$name"}, count: { $sum: 1 } } }, {$match:{count:{$gt:1}}} ] )

feihuadao的专栏 5009

mongodb group 有条件的过滤组合个数。

1.统计个数,这种方式比较快。 db.trace_2015_01_01.aggregate([{ $match : { _id:{ "$gt":3309432 } } },{$group : {_id : "$operate", num_tutorial : {$sum : 1}}}]); 2.这种方式是mapreduce的方式,很慢 db.trace_2015_01_01.group({

Terry - 专注外贸B2C 3921
上一篇: VBA实现Excel模块筛选高级应用场景!
下一篇: 深入浅出设计模式:模板模式
饶艳辉
博客等级 码龄15年 20粉丝 46原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值