使用mongodb进行mapreduce运算

Posted on 2021-08-19 15:25  Bumon  阅读(201)  评论(0)    收藏  举报

前言

记录一下mongodb mapreduce的过程


导入数据

[root@iZwz96vtq89cjkainh889cZ bin]# mongoimport --port 28010 --authenticationDatabase admin --username root --password root --db test --collection books --file /home/vscode/lots/data/books.json

#导出
[root@iZwz96vtq89cjkainh889cZ ~]# mongoexport --port 28010 --authenticationDatabase admin --username root --password root --db test --collection book_res_sum -f bookcount,count --csv --out ./book_res_sum.csv
mongoexport --port 28010 --authenticationDatabase admin --username root --password root --db test --collection book_res_sum -f _id,value --csv --out ./book_res_sum.csv
mongoexport --port 28010 --authenticationDatabase admin --username root --password root --db test --collection book_res_lt100 -f _id,value --csv --out ./book_res_lt100.csv
mongoexport --port 28010 --authenticationDatabase admin --username root --password root --db test --collection book_res_exp -f _id,value --csv --out ./book_res_exp.csv
mongoexport --port 28010 --authenticationDatabase admin --username root --password root --db test --collection book_res_year -f _id,value --csv --out ./book_res_year.csv
mongoexport --port 28010 --authenticationDatabase admin --username root --password root --db test --collection book_res_pricecount -f _id,value --csv --out ./book_res_pricecount.csv

[root@iZwz96vtq89cjkainh889cZ ~]# sz book_res_*
#上面的是lrzsz传输工具,从服务器传文件到终端,这里用它获取导出的csv文件到本地

MapReduce设计

大概看看每个书籍包括什么数据

#每个书籍所包含的数据
"_id" : "001-002",
"书名" : "白夏",
"作者" : "[日] 安达充  /   [日] 武论尊",
"出版社" : "小学馆",
"页数" : "50",
"装帧" : "平装",
"image_urls" : 
"简介" :

统计图书的总册数

m=function(){
    if(this._id){
        emit("bookCount",1);
    }else{emit("bookCount",0)};
}
r=function(key,values){
    return Array.sum(values);
}
res =db.runCommand({
mapreduce:"books",
map:m,
reduce:r,
out:"book_res_sum",
// query:{classID:{$eq:00}}
})
db.book_res_sum.find()
rs1:PRIMARY> db.book_res_sum.find()
{ "_id" : "bookCount", "value" : 202904 }

统计价格大于100元的图书占比多少

m=function(){
    if(parseFloat(this.定价)>100.0){
        emit("bookPrice",1);
    }else{emit("bookPrice",0)};
}
r=function(key,values){
    return Array.sum(values);
}
res =db.runCommand({
mapreduce:"books",
map:m,
reduce:r,
out:"book_res_lt100",
// query:{classID:{$eq:00}}
})
db.book_res_lt100.find()
rs1:PRIMARY> db.book_res_lt100.find()
{ "_id" : "bookPrice", "value" : 15783 }

统计各个出版社的占比

m=function(){
    emit(this.出版社,1);
}
r=function(key,values){
    return Array.sum(values);
}
res =db.runCommand({
mapreduce:"books",
map:m,
reduce:r,
out:"book_res_exp",
// query:{classID:{$eq:00}}
})
db.book_res_exp.find()
rs1:PRIMARY> db.book_res_exp.find()
{ "_id" : null, "value" : 7103 }
{ "_id" : "", "value" : 275 }
{ "_id" : "\b遠東圖書公司", "value" : 1 }
{ "_id" : ""Harry N. Abrams, Inc."", "value" : 4 }
{ "_id" : ""湖南科学技术出版社"", "value" : 1 }
{ "_id" : "(勤+緣)衛斯理科幻系列(3)‧衛斯理", "value" : 1 }
{ "_id" : "(影印版) (2002年1月1日)", "value" : 1 }
{ "_id" : "(株) リトル・モア", "value" : 1 }
{ "_id" : "(株)ふゅーじょんぷろだくと", "value" : 2 }
{ "_id" : "(株)六耀社", "value" : 1 }
{ "_id" : "(知识产权)专利文献出版社", "value" : 2 }
{ "_id" : "(香港)勤+缘出版社 太白文艺出版社", "value" : 1 }
{ "_id" : ".A.P./Distributed Art Publishers, Inc.", "value" : 1 }
{ "_id" : "/广西美术出版社", "value" : 1 }
{ "_id" : "/河圖文化", "value" : 1 }
{ "_id" : "010", "value" : 2 }
{ "_id" : "010 Publishers", "value" : 1 }
{ "_id" : "010 Uitgeverij", "value" : 2 }
{ "_id" : "1-4000", "value" : 1 }
{ "_id" : "1000BUNKO", "value" : 1 }
Type "it" for more
rs1:PRIMARY> it
{ "_id" : "1000BUNKU", "value" : 1 }
{ "_id" : "100PAGES PRESS", "value" : 1 }
{ "_id" : "112", "value" : 1 }
{ "_id" : "1908有限公司", "value" : 1 }
{ "_id" : "1958年", "value" : 1 }
{ "_id" : "1984", "value" : 1 }
{ "_id" : "1985.8", "value" : 1 }
{ "_id" : "1990年3月", "value" : 1 }
{ "_id" : "1991", "value" : 2 }
{ "_id" : "1994", "value" : 1 }
{ "_id" : "1998", "value" : 1 }
{ "_id" : "1998-10", "value" : 1 }
{ "_id" : "1999", "value" : 1 }
{ "_id" : "1st World Library", "value" : 1 }
{ "_id" : "1st World Library - Literary Society", "value" : 1 }
{ "_id" : "1月と7月", "value" : 1 }
{ "_id" : "2003", "value" : 1 }
{ "_id" : "2003-2-1 00\\:00\\:00", "value" : 1 }
{ "_id" : "2006 年 10 月 15 日", "value" : 1 }
{ "_id" : "2006-5", "value" : 1 }
Type "it" for more
rs1:PRIMARY> 

最近10年出版图书数量

m=function(){
    let Publicy=this.出版年;
    if(/2011$/.test(Publicy)){
        emit("2011",1);
    }else if(/2012$/.test(Publicy)){
        emit("2012",1);
    }else if(/2013$/.test(Publicy)){
        emit("2013",1);
    }else if(/2014$/.test(Publicy)){
        emit("2014",1);
    }else if(/2015$/.test(Publicy)){
        emit("2015",1);
    }else if(/2016$/.test(Publicy)){
        emit("2016",1);
    }else if(/2017$/.test(Publicy)){
        emit("2017",1);
    }else if(/2018$/.test(Publicy)){
        emit("2018",1);
    }else if(/2019$/.test(Publicy)){
        emit("2019",1);
    }else if(/2020$/.test(Publicy)){
        emit("2020",1);
    }else if(/2021$/.test(Publicy)){
        emit("2021",1);
    }
}
r=function(key,values){
    return Array.sum(values);
}
res =db.runCommand({
mapreduce:"books",
map:m,
reduce:r,
out:"book_res_year",
// query:{classID:{$eq:00}}
})
db.book_res_year.find()
rs1:PRIMARY> db.book_res_year.find()
{ "_id" : "2011", "value" : 61 }
{ "_id" : "2012", "value" : 56 }
{ "_id" : "2013", "value" : 51 }
{ "_id" : "2014", "value" : 54 }
{ "_id" : "2015", "value" : 53 }
{ "_id" : "2016", "value" : 45 }
{ "_id" : "2017", "value" : 41 }
{ "_id" : "2018", "value" : 27 }
{ "_id" : "2019", "value" : 19 }
rs1:PRIMARY> 

各个价格区间图书数量

设定价格区间为:below10 10-20 20-30 30-40 40-50 over50

m=function(){
    let price=this.定价;
    if(price>0&&price<=10){
        emit("0~10",1);
    }else if(price>10&&price<=20){
        emit("10~20",1);
    }else if(price>20&&price<=30){
        emit("20~30",1);
    }else if(price>30&&price<=40){
        emit("30~40",1);
    }else if(price>40&&price<=50){
        emit("40~50",1);
    }else if(price>50){
        emit("50~inf",1);
    }
}
r=function(key,values){
    return Array.sum(values);
}
res =db.runCommand({
mapreduce:"books",
map:m,
reduce:r,
out:"book_res_pricecount",
// query:{classID:{$eq:00}}
})
db.book_res_pricecount.find()
rs1:PRIMARY> db.book_res_pricecount.find()
{ "_id" : "0~10", "value" : 4805 }
{ "_id" : "10~20", "value" : 6390 }
{ "_id" : "20~30", "value" : 6636 }
{ "_id" : "30~40", "value" : 7362 }
{ "_id" : "40~50", "value" : 5067 }
{ "_id" : "50~inf", "value" : 11165 }
rs1:PRIMARY> 

数据库中

可视化设计

打算采用vue+elements+echarts来用网页实现数据可视化

安装环境

[root@iZwz96vtq89cjkainh889cZ vscode]# yum install npm
#安装nvm管理node版本-------------
[root@iZwz96vtq89cjkainh889cZ vscode]# curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.1/install.sh | bash
[root@iZwz96vtq89cjkainh889cZ vscode]# source ~/.bashrc
[root@iZwz96vtq89cjkainh889cZ vscode]# nvm install stable #安装最新稳定版
[root@iZwz96vtq89cjkainh889cZ vscode]# nvm use
[root@iZwz96vtq89cjkainh889cZ vscode]# node -v
#安装vue脚手架--------------------
[root@iZwz96vtq89cjkainh889cZ vscode]# npm install -g @vue/cli
[root@iZwz96vtq89cjkainh889cZ vscode]# vue --version
#新建vue项目---------------------
[root@iZwz96vtq89cjkainh889cZ vscode]# vue create coursedesign
#安装echarts和elementui
[root@iZwz96vtq89cjkainh889cZ vscode]# npm install echarts -S
[root@iZwz96vtq89cjkainh889cZ vscode]# npm i element-ui -S

繁琐又不失优雅的页面设计

直接放仓库看代码吧(哦豁本来想用vue的,但本机和服务器的脚手架都被我装崩了,迫于时间只能更换方案…

更换方案

主机和服务器nvm环境都崩了,鉴于时间关系换可视化方案

选用了python的Pyechart来画图

结果

遇到的错误(mongodb)

错误1:无法连接到服务

[root@iZwz96vtq89cjkainh889cZ bin]# mongoimport --db test --collection bookdemo --file /home/vscode/lots/data/books-sample.json
2021-06-22T21:42:33.165+0800    error connecting to host: could not connect to server: server selection error: server selection timeout, current topology: { Type: Single, Servers: [{ Addr: localhost:27017, Type: Unknown, State: Connected, Average RTT: 0, Last error: connection() : dial tcp [::1]:27017: connect: connection refused }, ] }

原因是配置了分布式,端口不是mongodb的默认端口,且用户权限有问题

[root@iZwz96vtq89cjkainh889cZ bin]# mongoimport --port 28010 --authenticationDatabase admin --username root --password root --db test --collection bookdemo --file /home/vscode/lots/data/books-sample.json
2021-06-22T22:06:48.144+0800    connected to: mongodb://localhost:28010/
2021-06-22T22:06:48.230+0800    500 document(s) imported successfully. 0 document(s) failed to import.

查看结果

rs1:PRIMARY> show collections
bookdemo
rs1:PRIMARY> show dbs
admin   0.001GB
c1      0.000GB
config  0.000GB
local   0.002GB
test    0.000GB
rs1:PRIMARY> show collections
bookdemo
rs1:PRIMARY> db.bookdemo.find().pretty()
{
        "_id" : "001-002",
        "书名" : "白夏",
        "作者" : "[日] 安达充  /   [日] 武论尊",
        "出版社" : "小学馆",
        "页数" : "50",
        "装帧" : "平装",
        "image_urls" : "https://img1.doubanio.com/view/subject/l/public/s3531089.jpg",
        "简介" : "《白夏》在安达充的作品里算得上是比较特殊的一个,因为它是唯一个由武论尊老师提供原作,而安达老师只负责作画的作品,故事虽短,却很感人。恒内武郎和市村哲是自小的好朋友,他们在一个队里打棒球,恒内是捕手而哲是投手。在一次比赛中,因为恒内的失误,全队没能进入甲子园,虽然哲并不怪恒内,但恒内却很自责。“和这种温和的话相比,我倒宁愿被你痛打一顿来的好受点呢。”之后,哲便离开了家乡,而恒内留下来做了警察。几年后,哲回来了,但却是一个身负多次刺伤人的罪名的逃犯。两人第一次见面后,哲对恒内说“我还有必须要做的事情”便离开了。不久,又有一人被哲开枪射伤,恒内追捕哲到了悬崖边上。“为什么不马上离开这个镇子?”“为什么要回来?”“有很多原因,很多...呢。”“人总会不小心失误。”“而当失误一再出现,到最后就不能再叫失误了。”恒内最终还是开了枪,但却在之后才知道原来哲枪杀的那人是恒内办案时得罪的组织派来的杀手,而同是那个组织成员的哲知道了这个情报后才特意赶来救恒内的。组织的头目被逮捕了,但恒内是怎样的一种心情呢。\n“打棒球并不是只为了胜利,是为了朋友,一生的朋友...”但追逐白球的那个夏天,却再也回不来了......\n各位喜欢安达充世界的读者,对不起了,我给这个温馨的世界加入了异色。不过,安达充巨匠也好,我也好,都还在做着进化,很想向未知的世界挑战。假使,各位对这部作品是在很不满意,请不要迁怒于《少年SUNDAY》,还是以宽容的心来看吧。\n——武论尊\n接下这个工作,只是单纯因为想看到“原作/武论尊、作画/安达充”的标志而已。和武论尊老师也有20多年的交情了吧,不过要说组成工作搭档,这还是第一次。总之,很久没画过有原作的作品了,觉得蛮新鲜刺激的,心情也变得相当好。\n——安达充"
}
{
        "_id" : "1-3",
        "书名" : "白衣剑卿",
        "作者" : "瑞者",
        "出版年" : "2009",
        "页数" : "600",
        "装帧" : "精装",
        "image_urls" : "https://img1.doubanio.com/view/subject/l/public/s4646047.jpg",
        "简介" : "文案\n依稀間,他記起,寒風凜冽,荒草古道之間,白衣赤馬,悠然而至。\n初見,他送他一壇美酒 ,不及相談,他給予他燦然一笑。\n他問他是誰,他一聲長笑,長吟出自己的名號,打馬而去,留給他一個遙不可及的瀟灑背影。\n白衣折梅駕火影,側身天地一劍卿......\n劍卿劍卿,因著一枚小小的鎖情針,白衣劍卿情鎖白赤宮,甘做他人男妾雌伏胯下,身敗名裂為人唾棄,一段江湖孽緣催人淚下。\n難道一定要到失去時才明白曾經的擁有麼?"
}
#看起来json的数据有点问题

遇到的错误(vue)

(忘记记录了