来,我给你们看一段神奇的mongodb的mapreduce操作!
首先我们执行一段js,用来往mongodb数据库里插入几条记录:
//insert.js
for(var i=0;i<5;i++){
db.RegistRecord.save({"ip":"11.11.11.11","account":"ongyong"});
}
for(var i=0;i<2;i++){
db.RegistRecord.save({"ip":"11.11.11.22","account":"ongyong22"});
}
for(var i=0;i<1;i++){
db.RegistRecord.save({"ip":"11.11.11.33","account":"ongyong33"});
}
没有问题,随后我们来使用mongodb的mapreduce来进行一个统计,统计同一ip在记录里出现的次数,很简单的mapreduce入门例子,写法如下,不多解释。
//regmp.js
printjson("job start");
var map = function() {
emit(this.ip, {value: 1});
}
var reduce = function(key, values) {
var count = 0;
values.forEach(function(v) {
count += v['value'];
});
return {count: count };
}
var res = db.runCommand({mapreduce:"RegistRecord",map:map, reduce:reduce, out:"log_results"});
printjson("job end")
然后我们执行这个js脚本。
我们看结果:
/* 0 */
{
"_id" : "11.11.11.11",
"value" : {
"count" : 5.0
}
}
/* 1 */
{
"_id" : "11.11.11.22",
"value" : {
"count" : 2.0
}
}
/* 2 */
{
"_id" : "11.11.11.33",
"value" : {
"value" : 1.0
}
}
OK,运算结果正确,各ip分别出现了5次,2次,1次。
OK,到这里,如果你认为我就是要为了演示这个东西,那我肯定是来找喷的,哥们儿,这特么一点也不神奇。神奇的事情在下面,我们继续看:
当我们把记录数增加到某一个量级,(如2000)
//insert.js
for(var i=0;i<2000;i++){
db.RegistRecord.save({"ip":"11.11.11.11","account":"ongyong"});
}
for(var i=0;i<2;i++){
db.RegistRecord.save({"ip":"11.11.11.22","account":"ongyong22"});
}
for(var i=0;i<1;i++){
db.RegistRecord.save({"ip":"11.11.11.33","account":"ongyong33"});
}
然后我们再次执行regmp.js这段代码运行mapreduce,注意,绝对没有任何改动,这时,神奇的事情出现了,看结果:
/* 0 */
{
"_id" : "11.11.11.11",
"value" : {
"count" : NaN
}
}
/* 1 */
{
"_id" : "11.11.11.22",
"value" : {
"count" : 2.0
}
}
/* 2 */
{
"_id" : "11.11.11.33",
"value" : {
"value" : 1.0
}
}
11.11.11.11这个ip的结果出现了一个非数值型字符串!!!而其余两个正确。神奇啊!不明白啊!困惑啊!!
然而,我得找原因啊,我想知道,到底在经过map函数后,reduce函数接受到的values的格式是怎样的,我稍微改了下reduce函数,我不进行任何操作,直接把value作为结果保存。
改动后的Reduce函数如下:
var reduce = function(key, values) {
return {count: values };
}
首先,看记录数各为:5,2,1时,经过map函数处理,然后传给reduce函数的参数格式如下:
/* 0 */
{
"_id" : "11.11.11.11",
"value" : {
"count" : [{
"value" : 1.0
}, {
"value" : 1.0
}, {
"value" : 1.0
}, {
"value" : 1.0
}, {
"value" : 1.0
}]
}
}
/* 1 */
{
"_id" : "11.11.11.22",
"value" : {
"count" : [{
"value" : 1.0
}, {
"value" : 1.0
}]
}
}
/* 2 */
{
"_id" : "11.11.11.33",
"value" : {
"value" : 1.0
}
}
没有问题!传到reduce函数中的value是一个固定格式的json串。我们可以对count中的各元素进行数值运算。
然后,我们看记录数为2000的,结果:
/* 0 */
{
"_id" : "11.11.11.22",
"value" : {
"count" : [{
"value" : 1.0
}, {
"value" : 1.0
}]
}
}
/* 1 */
{
"_id" : "11.11.11.33",
"value" : {
"value" : 1.0
}
}
/* 2 */
{
"_id" : "11.11.11.11",
"value" : {
"count" : [{
"count" : [{
"value" : 1.0
}, {
"value" : 1.0
}, {
"value" : 1.0
}, {
。。。。此处省略后面记录
看!!!最后这条记录!瞎了吧!!!传过来的values值的结构都改变了!!!无缘无故的嵌套了几层count,再用 count += v['value']当然没法进行数值运行啦!!!坑爹啊!!!为什么???
注:
Mongodb版本 2.0.1 ,32bit
环境:windowxp 32bit
(少废话,我生产环境当然是用的linux,我这不是做实验么)
我要吃晚饭了先,linux环境我稍后回来继续做~