麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 數(shù)據(jù)庫 > MongoDB > 正文

MongoDB中強大的統(tǒng)計框架Aggregation使用實例解析

2020-03-14 13:18:08
字體:
供稿:網(wǎng)友
這篇文章主要介紹了MongoDB中強大的統(tǒng)計框架Aggregation使用實例解析,文中舉了Python和Java使用Aggregation的數(shù)據(jù)統(tǒng)計例子進行講解,需要的朋友可以參考下
 

聽說項目里面Aggregation用的多,那就專門針對這個多多練習一下。

基本的操作包括:

•$project - 可以從子文檔中提取字段,可以重命名字段

•$match - 可以實現(xiàn)查找的功能

•$limit - 接受一個數(shù)字n,返回結果集中的前n個文檔。

•$skip - 接受一個數(shù)字n,丟棄結果集中的前n個文檔。效率比較低,依然會遍歷前n個文檔。

•$unwind - 可以將一個包含數(shù)組的文檔切分成多個, 比如你的文檔有 中有個數(shù)組字段 A, A中有10個元素, 那么經(jīng)過 $unwind處理后會產(chǎn)生10個文檔,這些文檔只有 字段 A不同

•$group - 統(tǒng)計操作, 還提供了一系列子命令

–$avg, $sum …

•$sort - 排序

Python篇
實驗一、學生數(shù)據(jù)統(tǒng)計

1、生成學生數(shù)據(jù):

#!/usr/bin/env python# coding=utf-8from pymongo import MongoClientfrom random import randintname1 = ["yang ", "li ", "zhou "]name2 = [  "chao",  "hao",  "gao",  "qi gao",  "hao hao",  "gao gao",  "chao hao",  "ji gao",  "ji hao",  "li gao",  "li hao",]provinces = [  "guang dong",  "guang xi",  "shan dong",  "shan xi",  "he nan"]client = MongoClient('localhost', 27017)db = client.studentsm = db.smessagesm.remove()for i in range(1, 100):  name = name1[randint(0, 2)] + name2[randint(0, 10)]  province = provinces[randint(0, 4)]  new_student = {    "name": name,    "age": randint(1, 30),    "province": province,    "subject": [      {"name": "chinese", "score": randint(0, 100)},      {"name": "math", "score": randint(0, 100)},      {"name": "english", "score": randint(0, 100)},      {"name": "chemic", "score": randint(0, 100)},    ]}  print new_student  sm.insert_one(new_student)print sm.count()

好了,現(xiàn)在數(shù)據(jù)庫里面有100條學生數(shù)據(jù)了。

現(xiàn)在我要得到廣東學生的平均年齡,在mongo控制臺輸入:

 如果想到得到所有省份的平均年齡,那就更加簡單了:

db.smessage.aggregate({$match: {province: "guang dong"}}){ "_id" : "guang xi", "age" : 15.19047619047619 }{ "_id" : "guang dong", "age" : 16.05263157894737 }{ "_id" : "shan dong", "age" : 17.44 }{ "_id" : "he nan", "age" : 20 }{ "_id" : "shan xi", "age" : 16.41176470588235 }

如果想得到廣東省所有科目的平均成績:

db.smessage.aggregate({$match: {province: "guang dong"}},{$unwind: "$subject"},{$group: { _id: {province:"$province",sujname:"$subject.name"}, per:{$avg:"$subject.score"}}})

加上排序:

db.smessage.aggregate({$match: {province: "guang dong"}},{$unwind: "$subject"},{$group: { _id: {province:"$province",sujname:"$subject.name"}, per:{$avg:"$subject.score"}}},{$sort:{per:1}})

實驗二、尋找發(fā)帖水王
有一個保存著雜志文章的集合,你可能希望找出發(fā)表文章最多的那個作者。假設每篇文章被保存為MongoDB中的一個文檔。

1、插入數(shù)據(jù)

#!/usr/bin/env python# coding=utf-8from pymongo import MongoClientfrom random import randintname = [  'yangx',  'yxxx',  'laok',  'kkk',  'ji',  'gaoxiao',  'laoj',  'meimei',  'jj',  'manwang',]title = [  '123',  '321',  '12',  '21',  'aaa',  'bbb',  'ccc',  'sss',  'aaaa',  'cccc',]client = MongoClient('localhost', 30999)db = client.testbbs = db.bbsbbs.remove()for i in range(1, 10000):  na = name[randint(0, 9)]  ti = title[randint(0, 9)]  newcard = {    'author': na,    'title': ti,  }  bbs.insert_one(newcard)print bbs.count()

現(xiàn)在我們擁有了10000條文章數(shù)據(jù)了。

2、用$project將author字段投射出來

{"$project": {"author":1}}

這個語法與查詢中的字段選擇器比較像:可以通過指定"fieldname" : 1選擇需要投射的字段,或者通過指定"fieldname":0排除不需要的字段。

執(zhí)行完這個"$project"操作之后,結果集中的每個文檔都會以{"_id" : id, "author" : "authorName"}這樣的形式表示。這些結果只會在內(nèi)存中存在,不會被寫入磁盤。

3、用group將作者名稱分組

{"group":{"_id":"$author","count":{"$sum":1}}}

這樣就會將作者按照名字排序,某個作者的名字每出現(xiàn)一次,就會對這個作者的"count"加1。

這里首先指定了需要進行分組的字段"author"。這是由"_id" : "$author"指定的。可以將這個操作想象為:這個操作執(zhí)行完后,每個作者只對應一個結果文檔,所以"author"就成了文檔的唯一標識符("_id")。

第二個字段的意思是為分組內(nèi)每個文檔的"count"字段加1。注意,新加入的文檔中并不會有"count"字段;這"$group"創(chuàng)建的一個新字段。

執(zhí)行完這一步之后,結果集中的每個文檔會是這樣的結構:{"_id" : "authorName", "count" : articleCount}。

4、用sort排序

{"$sort" : {"count" : -1}}

這個操作會對結果集中的文檔根據(jù)"count"字段進行降序排列。

5、限制結果為前5個文檔

{"$limit" : 5}

這個操作將最終的返回結果限制為當前結果中的前5個文檔。
在MongoDB中實際運行時,要將這些操作分別傳給aggregate()函數(shù):

> db.articles.aggregate({"$project" : {"author" : 1}},... {"$group" : {"_id" : "$author", "count" : {"$sum" : 1}}},... {"$sort" : {"count" : -1}},... {"$limit" : 5}... )

aggregate()會返回一個文檔數(shù)組,其中的內(nèi)容是發(fā)表文章最多的5個作者。

{ "_id" : "yangx", "count" : 1028 }{ "_id" : "laok", "count" : 1027 }{ "_id" : "kkk", "count" : 1012 }{ "_id" : "yxxx", "count" : 1010 }{ "_id" : "ji", "count" : 1007 }
Java篇

我在db中造了些數(shù)據(jù)(數(shù)據(jù)時隨機生成的, 能用即可),沒有建索引,文檔結構如下:

Document結構:

 {  "_id" : ObjectId("509944545"),  "province" : "海南",  "age" : 21,  "subjects" : [  {  "name":"語文",  "score" : 53  },  {  "name":"數(shù)學",  "score" : 27  },  {  "name":"英語",  "score" : 35  }   ],  "name" : "劉雨" }

     接下來要實現(xiàn)兩個功能:

  1.     統(tǒng)計上海學生平均年齡
  2.     統(tǒng)計每個省各科平均成績

接下來一一道來

統(tǒng)計上海學生平均年齡

從這個需求來講,要實現(xiàn)功能要有幾個步驟: 1. 找出上海的學生. 2. 統(tǒng)計平均年齡 (當然也可以先算出所有省份的平均值再找出上海的)。如此思路也就清晰了

首先上 $match, 取出上海學生

{$match:{'province':'上海'}}

接下來 用 $group 統(tǒng)計平均年齡

{$group:{_id:'$province',$avg:'$age'}}

$avg 是 $group的子命令,用于求平均值,類似的還有 $sum, $max ....
上面兩個命令等價于

select province, avg(age)  from student  where province = '上海' group by province

下面是Java代碼

Mongo m = new Mongo("localhost", 27017); DB db = m.getDB("test"); DBCollection coll = db.getCollection("student");  /*創(chuàng)建 $match, 作用相當于query*/ DBObject match = new BasicDBObject("$match", new BasicDBObject("province", "上海"));  /* Group操作*/ DBObject groupFields = new BasicDBObject("_id", "$province"); groupFields.put("AvgAge", new BasicDBObject("$avg", "$age")); DBObject group = new BasicDBObject("$group", groupFields);  /* 查看Group結果 */ AggregationOutput output = coll.aggregate(match, group); // 執(zhí)行 aggregation命令 System.out.println(output.getCommandResult());

輸出結果:

{ "serverUsed" : "localhost/127.0.0.1:27017" ,     "result" : [   { "_id" : "上海" , "AvgAge" : 32.09375}  ] ,       "ok" : 1.0 }

如此工程就結束了,再看另外一個需求

統(tǒng)計每個省各科平均成績

首先更具數(shù)據(jù)庫文檔結構,subjects是數(shù)組形式,需要先‘劈'開,然后再進行統(tǒng)計

主要處理步驟如下:

1. 先用$unwind 拆數(shù)組 2. 按照 province, subject 分租并求各科目平均分

$unwind 拆數(shù)組

{$unwind:'$subjects'}

按照 province, subject 分組,并求平均分

{$group:{   _id:{     subjname:”$subjects.name”,  // 指定group字段之一 subjects.name, 并重命名為 subjname     province:'$province'     // 指定group字段之一 province, 并重命名為 province(沒變)   },   AvgScore:{    $avg:”$subjects.score”    // 對 subjects.score 求平均   } }

java代碼如下:

Mongo m = new Mongo("localhost", 27017); DB db = m.getDB("test"); DBCollection coll = db.getCollection("student");  /* 創(chuàng)建 $unwind 操作, 用于切分數(shù)組*/ DBObject unwind = new BasicDBObject("$unwind", "$subjects");  /* Group操作*/ DBObject groupFields = new BasicDBObject("_id", new BasicDBObject("subjname", "$subjects.name").append("province", "$province")); groupFields.put("AvgScore", new BasicDBObject("$avg", "$subjects.scores")); DBObject group = new BasicDBObject("$group", groupFields);  /* 查看Group結果 */ AggregationOutput output = coll.aggregate(unwind, group); // 執(zhí)行 aggregation命令 System.out.println(output.getCommandResult());

輸出結果

{ "serverUsed" : "localhost/127.0.0.1:27017" ,   "result" : [    { "_id" : { "subjname" : "英語" , "province" : "海南"} , "AvgScore" : 58.1} ,    { "_id" : { "subjname" : "數(shù)學" , "province" : "海南"} , "AvgScore" : 60.485} ,   { "_id" : { "subjname" : "語文" , "province" : "江西"} , "AvgScore" : 55.538} ,    { "_id" : { "subjname" : "英語" , "province" : "上海"} , "AvgScore" : 57.65625} ,    { "_id" : { "subjname" : "數(shù)學" , "province" : "廣東"} , "AvgScore" : 56.690} ,    { "_id" : { "subjname" : "數(shù)學" , "province" : "上海"} , "AvgScore" : 55.671875} ,   { "_id" : { "subjname" : "語文" , "province" : "上海"} , "AvgScore" : 56.734375} ,    { "_id" : { "subjname" : "英語" , "province" : "云南"} , "AvgScore" : 55.7301 } ,   .   .   .   .   "ok" : 1.0 }

統(tǒng)計就此結束.... 稍等,似乎有點太粗糙了,雖然統(tǒng)計出來的,但是根本沒法看,同一個省份的科目都不在一起。囧

接下來進行下加強,

支線任務: 將同一省份的科目成績統(tǒng)計到一起( 即,期望 'province':'xxxxx', avgscores:[ {'xxx':xxx}, ....] 這樣的形式)

要做的有一件事,在前面的統(tǒng)計結果的基礎上,先用 $project 將平均分和成績?nèi)嗟揭黄穑葱稳缦旅娴臉幼?/p>

{ "subjinfo" : { "subjname" : "英語" ,"AvgScores" : 58.1 } ,"province" : "海南" }

再按省份group,將各科目的平均分push到一塊,命令如下:

$project 重構group結果

{$project:{province:"$_id.province", subjinfo:{"subjname":"$_id.subjname", "avgscore":"$AvgScore"}}

$使用 group 再次分組

{$group:{_id:"$province", avginfo:{$push:"$subjinfo"}}}

java 代碼如下:

Mongo m = new Mongo("localhost", 27017);DB db = m.getDB("test");DBCollection coll = db.getCollection("student");       /* 創(chuàng)建 $unwind 操作, 用于切分數(shù)組*/DBObject unwind = new BasicDBObject("$unwind", "$subjects");       /* Group操作*/DBObject groupFields = new BasicDBObject("_id", new BasicDBObject("subjname", "$subjects.name").append("province", "$province"));groupFields.put("AvgScore", new BasicDBObject("$avg", "$subjects.scores"));DBObject group = new BasicDBObject("$group", groupFields);       /* Reshape Group Result*/DBObject projectFields = new BasicDBObject();projectFields.put("province", "$_id.province");projectFields.put("subjinfo", new BasicDBObject("subjname","$_id.subjname").append("avgscore", "$AvgScore"));DBObject project = new BasicDBObject("$project", projectFields);       /* 將結果push到一起*/DBObject groupAgainFields = new BasicDBObject("_id", "$province");groupAgainFields.put("avginfo", new BasicDBObject("$push", "$subjinfo"));DBObject reshapeGroup = new BasicDBObject("$group", groupAgainFields); /* 查看Group結果 */AggregationOutput output = coll.aggregate(unwind, group, project, reshapeGroup);System.out.println(output.getCommandResult());

結果如下:

{ "serverUsed" : "localhost/127.0.0.1:27017" ,  "result" : [     { "_id" : "遼寧" , "avginfo" : [ { "subjname" : "數(shù)學" , "avgscore" : 56.46666666666667} , { "subjname" : "英語" , "avgscore" : 52.093333333333334} , { "subjname" : "語文" , "avgscore" : 50.53333333333333}]} ,     { "_id" : "四川" , "avginfo" : [ { "subjname" : "數(shù)學" , "avgscore" : 52.72727272727273} , { "subjname" : "英語" , "avgscore" : 55.90909090909091} , { "subjname" : "語文" , "avgscore" : 57.59090909090909}]} ,     { "_id" : "重慶" , "avginfo" : [ { "subjname" : "語文" , "avgscore" : 56.077922077922075} , { "subjname" : "英語" , "avgscore" : 54.84415584415584} , { "subjname" : "數(shù)學" , "avgscore" : 55.33766233766234}]} ,     { "_id" : "安徽" , "avginfo" : [ { "subjname" : "英語" , "avgscore" : 55.458333333333336} , { "subjname" : "數(shù)學" , "avgscore" : 54.47222222222222} , { "subjname" : "語文" , "avgscore" : 52.80555555555556}]}   .  .  .  ] , "ok" : 1.0}


注:相關教程知識閱讀請移步到MongoDB頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 黄色网战入口 | 免费一级在线视频 | 一级电影免费在线观看 | 久久久久九九九女人毛片 | 99精品视频在线免费观看 | 27xxoo无遮挡动态视频 | 精品亚洲夜色av98在线观看 | 成人短视频在线观看免费 | 三级xxxx| 久久亚洲国产精品 | 久久精品日产高清版的功能介绍 | 色播久久 | 久久草在线视频国产 | 成人一区二区三区在线 | 国产91porn | 亚洲最新黄色网址 | 欧美性受xxxx白人性爽 | 欧美特黄a| 国产papa| 在线中文字幕亚洲 | 欧美成人一区二区三区 | 337p粉嫩大胆噜噜噜亚瑟影院 | 88xx成人永久免费观看 | 国产精品成人av片免费看最爱 | 被啪羞羞视频在线观看 | 成人毛片免费视频 | www.com香蕉| 精品亚洲一区二区 | 久久国产精品成人免费网站 | 激情网站免费观看 | 免费观看高清视频网站 | chinesexxxx刘婷hd 国产91在线播放九色 | 激情久久精品 | 国产日韩大片 | 中国fx性欧美xxxx | 午夜小电影 | 蜜桃视频观看麻豆 | 末成年女av片一区二区 | 最新亚洲国产 | 国产1区2区3区中文字幕 | 韩国美女一区 |