数据准备

  1. 下载国家地震数据 http://data.earthquake.cn/data/
  2. 通过navicat导入到数据库,方便和mysql语句做对比

shard分片集群配置

# step 1
mkdir -p ./data/shard/s0 ./data/shard/s1 #创建数据目录
mkdir -p ./data/shard/log # 创建日志目录
./bin/mongod --port 27017 --dbpath /usr/local/mongodb/data/shard/s0 --fork --logpath /usr/local/mongodb/data/shard/log/s0.log # 启动Shard Server实例1
./bin/mongod --port 27018 --dbpath /usr/local/mongodb/data/shard/s1 --fork --logpath /usr/local/mongodb/data/shard/log/s1.log # 启动Shard Server实例2 # step 2
mkdir -p ./data/shard/config #创建数据目录
./bin/mongod --port 27027 --dbpath /usr/local/mongodb/data/shard/config --fork --logpath /usr/local/mongodb/data/shard/log/config.log #启动Config Server实例 # step 3
./bin/mongos --port 4000 --configdb localhost:27027 --fork --logpath /usr/local/mongodb/data/shard/log/route.log --chunkSize=1 # 启动Route Server实例 # step 4
./bin/mongo admin --port 4000 #此操作需要连接admin库
> db.runCommand({ addshard:"localhost:27017" }) #添加 Shard Server 或者用 sh.addshard()命令来添加,下同;
{ "shardAdded" : "shard0000", "ok" : 1 }
> db.runCommand({ addshard:"localhost:27018" })
{ "shardAdded" : "shard0001", "ok" : 1 }
> db.runCommand({ enablesharding:"map" }) #设置分片存储的数据库
{ "ok" : 1 }
> db.runCommand({ shardcollection: "map.dz", key: { id:1 }}) # 设置分片的集合名称。且必须指定Shard Key,系统会自动创建索引,然后根据这个shard Key来计算
{ "collectionsharded" : "map.dz", "ok" : 1 } # 手动预先分片
for(var i=1;i<=30;i++) { sh.splitAt('map.dz',{id:i*1000}) }

然后通过MongoVUE把mysql中的数据导入到mongos(4000)中

数据分析实战

根据震级类型来求和

/******通过group******/
db.dz.group({
key:{type:1},
initial:{count:0},
reduce: function ( curr, result ) {
result.count ++;
}
})
// Error: group command failed: { "ok" : 0, "errmsg" : "can't do command: group on sharded collection" }
// group不能使用在分片上 /******通过聚合管道aggregate******/
db.dz.aggregate([
{
$group:{
_id:"$type",
count:{$sum:1}
}
} /******通过映射化简mapReduce******/
var map = function(){
emit(this.type,1); //把1映射到每个this.type上,然后sum就为count,还有一个技巧就是把count映射到1上,就是求总和
} var reduce = function(type,count){
var total = Array.sum(count);
// return {type:type,count:total}; 注意,这样返回是错误的,total是一个对象??? {type:type,count:count};
return total;
} //或者
var reduce = function(type,count){
var res = 0;
for (var i = 0; i < count.length;i++) {
res +=count[i];
}
return res;
} db.dz.mapReduce(map,reduce,{out:'res'});

根据日期来分组看哪一月的地震最多

/*****地震每日发生次数最多的地方*****/
db.dz.aggregate([
{ $group:{
_id:{date:"$date"}, //还不知道如何通过 date.substring(0,6)来分组,先跳过,做按日来分组,当然这里的date还是字符串,如果是日期类型的话,就好处理了,这就延伸出另外一个问题,字符串如何转换为时间类型;
count:{$sum:1},
}
},
{
$sort:{count:-1} // 做了个降序
},
{
$limit:1
}
]); /*****每日发生地震次数最多的10个地方,并求出最大值*****/
db.dz.aggregate([
{ $group:{
_id:{date:"$date",address:"$address"},
count:{$sum:1},
maxvalue:{$max:"$value"},
}
},
{
$sort:{count:-1}
},
{
$limit:10
}
]);

求每5个经纬度范围的地震次数;

var map = function(){
//映射到经纬度
var latitude = Math.floor(this.latitude/5)*5;
var longitude = Math.floor(this.longitude/5)*5; //除5下取整又乘以5,目的得到的经纬度都是5的倍数,也就是每隔5就一个数;
var block = latitude+':'+longitude;
emit(block,1); //总共统计每block出现地震的次数;
} var reduce = function(block,value){
return Array.sum(value);
} db.runCommand({
mapReduce:'dz',
map:map,
reduce:reduce,
out:'res'
}) db.res.find().sort({value:-1});

每月发生地震次数最多的10个地方,并求出震级最大值

方法一,该方法有误,未完成,先记录

注意,本方法有一些问题我是花了很多功夫都没解决,先记录一下,如果有玩mongoDB的朋友有缘看到这篇文章,又有心的话,希望留言指正;

当然,这属于技术上的一个钻牛角尖,其实完全可以绕开的...

var map = function(){
var date = this.date.substring(0,6);
emit(date,{count:this.address,value:this.value});//把地点和值映射到月份上
} var reduce = function(date,result){ /*
// 此时result的结构应该如下,为每月的地址数据明细
// 注意这里说的是应该,但实际上不是,这与我理解的mapReduce有误,并且我暂时还不能理解该结构最终为什么会呈现出差异,所以,我先按以下的结构,来在Reduce中做js处理
"result": [
{
"address": "新疆阿图什",
"value": 1.6
},
{
"address": "云南澜沧",
"value": 1.3
},
{
"address": "新疆哈密",
"value": 2
}
] //我想要得到的结果如下:
[{'四川木里':{count:2,max:5.2},'云南玉龙':{count:100,max:4.5}}]
*/ var arr = []; for (var i = 0; i < result.length;i++) {
var arrTmp = [result[i]];
var address = result[i]['address']; for (var j = i+1; j < result.length; j++) {
if(result[j]['address'] == address){
arrTmp.push(result[j]);
result.splice(j,1);
j--;
}
}; var value = [] for(var a=0; a <arrTmp.length;a++){
if(value.indexOf(arrTmp[a]['value']) == '-1'){
value.push(arrTmp[a]['value']);
}
} var max = 0;
for(var i=0;i<value.length;i++){
max = max < value[i]?value[i]:max;
} var ele = {};
ele[address] = {count:arrTmp.length,max:max};
arr.push(ele);
}
return {result:arr};
} db.runCommand({
mapReduce:'dz',
map:map,
reduce:reduce,
finalize:finalize, // 由于Reduce返回的结构是有误的,所以finalize还没办法处理,先留空;
out:'res'
})

方法二

本方法也有一个让我百思不得其解的问题,在注释部分有说明;

var map = function(){
var date = this.date.substring(0,6);
var map = date+'_'+this.address;
emit(map,{count:1,value:this.value});
} var reduce = function(date,result){
var count = 0;
for(var i=0;i<result.length;i++){
count += result[i]['count']; // result[i]['count']的值都是1
} //var count = result.length; // 一开始我的count值是这样写的,但是结果是错误的与mysql算出来的不符合,改成上面的才正确,这里也让我很郁闷,result[i]['count']的值都是1,result.length是其result元素的总合,按道理这个count和上面的count是一样的,但事实证明,我又错了,居然不一样....又是一个理解不了的问题; var value = [];
for(var i=0;i<result.length;i++){
value.push(result[i].value);
}
var max=0;
for(var i=0;i<value.length;i++){
max = max < value[i]?value[i]:max;
}
return {count:count,max:max};
} db.runCommand({
mapReduce:'dz',
map:map,
reduce:reduce,
out:'res'
}) db.res.find().sort({'value.count':-1}).limit(10); //在输出集合中再进行筛选
// 但是,第一多的数据和mysql算下来的不同,其后9名都是相同的

mongoDB系列文章到此先告一段落,后续再添加 【mongoDB高级篇】mongoDB在LBS中的应用; 2015-9-17

【mongoDB高级篇③】综合实战(1): 分析国家地震数据的更多相关文章

  1. 【mongoDB高级篇①】聚集运算之group,aggregate

    group 语法 db.collection.group({ key:{field:1},//按什么字段进行分组 initial:{count:0},//进行分组前变量初始化,该处声明的变量可以在以下 ...

  2. 【mongoDB高级篇①】聚集运算之group与aggregate

    group 语法   db.collection.group({ key:{field:1},//按什么字段进行分组 initial:{count:0},//进行分组前变量初始化,该处声明的变量可以在 ...

  3. Mongodb高级篇-性能优化

    1.监控 mongodb可以通过profile来监控数据,进行优化. 查看当前是否开启profile功能用命令:db.getProfilingLevel()返回level等级,值为0|1|2,分别代表 ...

  4. 【mongoDB高级篇②】大数据聚集运算之mapReduce(映射化简)

    简述 mapReduce从字面上来理解就是两个过程:map映射以及reduce化简.是一种比较先进的大数据处理方法,其难度不高,从性能上来说属于比较暴力的(通过N台服务器同时来计算),但相较于grou ...

  5. 「MySQL高级篇」explain分析SQL,索引失效&&常见优化场景

    大家好,我是melo,一名大三后台练习生 专栏回顾 索引的原理&&设计原则 欢迎关注本专栏:MySQL高级篇 本篇速览 在我们上一篇文章中,讲到了索引的原理&&设计原则 ...

  6. SpringBootTest单元测试实战、SpringBoot测试进阶高级篇之MockMvc讲解

    1.@SpringBootTest单元测试实战 简介:讲解SpringBoot的单元测试 1.引入相关依赖 <!--springboot程序测试依赖,如果是自动创建项目默认添加--> &l ...

  7. Salesforce学习之路-developer篇(五)一文读懂Aura原理及实战案例分析

    1. 什么是Lightning Component框架? Lightning Component框架是一个UI框架,用于为移动和台式设备开发Web应用程序.这是一个单页面Web应用框架,用于为Ligh ...

  8. MongoDB的真正性能-实战百万用户

    阅读目录 一.第一个问题:Key-Value数据库可以有好多的Key,没错,但对MongoDB来说,大错特错 二.第二个问题:FindOne({_id:xxx})就快么? 三.第三个问题:精细的使用U ...

  9. 面试题_Spring高级篇

    Spring高级篇 1.什么是 Spring 框架? Spring 框架有哪些主要模块?  Spring 框架是一个为 Java 应用程序的开发提供了综合.广泛的基础性支持的 Java 平台. Spr ...

随机推荐

  1. EL表达式jsp页面double小数点后保留两位

    EL表达式jsp页面double小数点后保留两位,四舍五入 <fmt:formatNumber type="number" value="${member.logi ...

  2. CC2530微处理器接口开发技术——信号灯的设计与实现

    本问主要介绍了CC2530处理器的通用输入/输出接口(GPIO),以及GPIO的位操作,理解GPIO的基本原理和功能,最后使用C语言驱动CC2530的GPIO实现对信号灯的控制. CC2530的GPI ...

  3. 网络扫描工具nmap

    nmap一般就用来扫描主机是否在线(特别是扫描局域网内存活的机器).开放了哪些端口.其他的功能用的比较少,做渗透的人可能要了解的多些. 1.1 选项说明 nmap需要自行安装. shell> y ...

  4. Docker镜像管理基础与基于容器的镜像制作示例

    一.Docker镜像 Docker镜像是启动Docker容器的一个非常重要的组件.Docker各组件之间的关系如图: Docker镜像含有启动容器所需要的文件系统及其内容,因此Docker镜像用于创建 ...

  5. Django 系列博客(一)

    Django 系列博客(一) 前言 学习了 python 这么久,终于到了Django 框架.这可以说是 python 名气最大的web 框架了,那么从今天开始会开始从 Django框架的安装到使用一 ...

  6. shell编程基础(五): 正则表达式及其使用

    正则表达式 1.前情提要 以前我们用grep在一个文件中找出包含某些字符串的行,比如在头文件中找出一个宏定义.其实grep还可以找出符合某个模式(Pattern)的一类字符串.例如找出所有符合xxxx ...

  7. golang高性能RPC:Apache Thrift安装使用完全攻略

    在企业应用中RPC的使用可以说是十分的广泛,使用该技术可以方便的与各种程序交互而不用考虑其编写使用的语言. 如果你对RPC的概念还不太清楚,可以点击这里. 现今市面上已经有许多应用广泛的RPC框架,比 ...

  8. Haskell复习笔记(一)

    Haskell笔记这是第三次总结,前两次都因为各种原因丢失了,对于Haskell我算不上什么大神,只不过在大学时为了学习算法时选择了Haskell. 当时的入门书籍选择的是<Learn You ...

  9. 【转载】 C#工具类:使用iTextSharp操作PDF文档

    iTextSharp是一个用于操作PDF文件的组件DLL程序,在C#程序中可以引用iTextSharp组件,用于开发与PDF文件相关的报表等功能,利用iTextSharp组件提供出来的方法接口,我们可 ...

  10. 重装系统之 Win10 镜像安装

    首先配置武器的第一步是要选择武器的性质,以前win10 刚出的时候有很多问题,导致大家都不太喜欢用,但是现在Win10 经过一系列的优化,已经相当稳定靠谱,但是网上很多重装系统的教程参差不齐,导致博主 ...