久久久精品一区ed2k-女人被男人叉到高潮的视频-中文字幕乱码一区久久麻豆樱花-俄罗斯熟妇真实视频

MongoDB(4):聚合框架

一、簡介

創(chuàng)新互聯(lián)主營范縣網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,成都app軟件開發(fā),范縣h5成都微信小程序搭建,范縣網(wǎng)站營銷推廣歡迎范縣等地區(qū)企業(yè)咨詢

MongoDB的聚合框架,主要用來對集合中的文檔進(jìn)行變換和組合,從而對數(shù)據(jù)進(jìn)行分析以加以利用。

聚合框架的基本思路是:

 采用多個(gè)構(gòu)件來創(chuàng)建一個(gè)管道,用于對一連串的文檔進(jìn)行處理。

這些構(gòu)件包括:

 篩選(filtering)、投影(projecting)、分組(grouping)、排序(sorting)、限制(limiting)和跳過(skipping)。

使用聚合框架的方式:

 db.集合.aggregate(構(gòu)件1,構(gòu)件2…)

注意:由于聚合的結(jié)果要返回到客戶端,因此聚合結(jié)果必須限制在16M以內(nèi),這是MongoDB支持的最大響應(yīng)消息的大小。

二、使用例子

2.1、準(zhǔn)備樣例數(shù)據(jù)

for(var i=0;i<100;i++){
    for(var j=0;j<4;j++){
        db.scores.insert({"studentId":"s"+i,"course":"課程"+j,"score":Math.random()*100});
    }
}

2.2、找出考80分以上的課程門數(shù)最多的3個(gè)學(xué)生

步驟:

 1:找到所有考了80分以上的學(xué)生,不區(qū)分課程

> db.scores.aggregate({"$match":{"score":{$gte:80}}});

2:將每個(gè)學(xué)生的名字投影出來

> db.scores.aggregate({"$match":{"score":{$gte:80}}},{$project:{"studentId":1}});

3:對學(xué)生的名字排序,某個(gè)學(xué)生的名字出現(xiàn)一次,就給他加1

> db.scores.aggregate({"$match":{"score":{$gte:80}}},{$project:{"studentId":1}},{$group:{"_id":"$studentId","count":{$sum:1}}});

4:對結(jié)果集按照count進(jìn)行降序排列

> db.scores.aggregate({"$match":{"score":{$gte:80}}},{$project:{"studentId":1}},{$group:{"_id":"$studentId","count":{$sum:1}}},{"$sort":{"count":-1}});

5:返回前面的3條數(shù)據(jù)

db.scores.aggregate({"$match":{"score":{$gte:80}}},{$project:{"studentId":1}},{$group:{"_id":"$studentId","count":{$sum:1}}},{"$sort":{"count":-1}},{"$limit":3});

MongoDB(4): 聚合框架三、管道操作符

每個(gè)操作符接受一系列的文檔,對這些文檔做相應(yīng)的處理,然后把轉(zhuǎn)換后的文檔作為結(jié)果傳遞給下一個(gè)操作符。最后一個(gè)操作符會(huì)將結(jié)果返回。

不同的管道操作符,可以按照任意順序,任意個(gè)數(shù)組合在一起使用。

3.1、篩選命令$match

用于對文檔集合進(jìn)行篩選,里面可以使用所有常規(guī)的查詢操作符。通常會(huì)放置在管道最前面的位置,理由如下:

 1:快速將不需要的文檔過濾,減少后續(xù)操作的數(shù)據(jù)量

 2:在投影和分組之前做篩選,查詢可以使用索引

3.2、投影命令$project

用來從文檔中提取字段,可以指定包含和排除字段,也可以重命名字段。比如要將studentId改為sid,如下:

db.scores.aggregate({"$project":{"sid":"$studentId"}})

管道操作符還可以使用表達(dá)式,以滿足更復(fù)雜的需求。

管道操作符$project的數(shù)學(xué)表達(dá)式:

比如給成績集體加20分,如下:

> db.scores.aggregate({"$project":{"studentId":1,"newScore":{$add:["$score",20]}}});

支持的操作符和相應(yīng)語法:

 1:$add : [expr1[,expr2,…exprn]]

 2:$subtract:[expr1,expr2]

 3:$multiply:[expr1[,expr2,…exprn]]

 4:$divice:[expr1,expr2]

 5:$mod:[expr1,expr2]

管道操作符$project的日期表達(dá)式:

聚合框架包含了一些用于提取日期信息的表達(dá)式,如下:

$year、$month、$week、$dayOfMonth、$dayOfWeek、$dayOfYear、$hour、$minute、$second 。

注意:這些只能操作日期型的字段,不能操作數(shù)據(jù),使用示例:

{"$project":{"opeDay":{"$dayOfMonth":"$recoredTime"}}}

管道操作符$project的字符串表達(dá)式:

1:$substr : [expr,開始位置,要取的字節(jié)個(gè)數(shù)]

2:$concat:[expr1[,expr2,…exprn]]

3:$toLower:expr

4:$toUpper:expr

例如:{"$project":{"sid":{$concat:["$studentId","cc"]}}}

管道操作符$project的邏輯表達(dá)式:

1:$cmp:[expr1,expr2] :比較兩個(gè)表達(dá)式,0表示相等,正數(shù)前面的大,負(fù)數(shù)后面的大

2:$strcasecmp:[string1,string2] :比較兩個(gè)字符串,區(qū)分大小寫,只對由羅馬字符組成的字符串有效

3:$eq、$ne、$gt、$gte、$lt、$lte :[expr1,expr2]

4:$and、$or、$not

5:$cond:[booleanExpr,trueExpr,falseExpr]:如果boolean表達(dá)式為true,返回true表達(dá)式,否則返回false表達(dá)式

6:$ifNull:[expr,otherExpr]:如果expr為null,返回otherExpr,否則返回expr

例如:db.scores.aggregate({"$project":{"newScore":{$cmp:["$studentId","sss"]}}})

3.3、分組命令$group

用來將文檔依據(jù)特定字段的不同值進(jìn)行分組。選定了分組字段過后,就可以把這些字段傳遞給$group函數(shù)的“_id”字段了。例如:

 db.scores.aggregate({“$group”:{“_id”:“$studentId”}}); 

 或者是

 db.scores.aggregate({"$group":{"_id":{"sid":"$studentId","score":"$score"}}});

$group支持的操作符:

1:$sum:value :對于每個(gè)文檔,將value與計(jì)算結(jié)果相加

2:$avg:value :返回每個(gè)分組的平均值

3:$max:expr :返回分組內(nèi)的最大值

4:$min:expr :返回分組內(nèi)的最小值

5:$first:expr :返回分組的第一個(gè)值,忽略其他的值,一般只有排序后,明確知道數(shù)據(jù)順序的時(shí)候,這個(gè)操作才有意義

6:$last:expr :與上面一個(gè)相反,返回分組的最后一個(gè)值

7:$addToSet:expr :如果當(dāng)前數(shù)組中不包含expr,那就將它加入到數(shù)組中

8:$push:expr:把expr加入到數(shù)組中

3.4、拆分命令$unwind

用來把數(shù)組中的每個(gè)值拆分成為單獨(dú)的文檔。

MongoDB(4): 聚合框架

3.5、排序命令$sort

可以根據(jù)任何字段進(jìn)行排序,與普通查詢中的語法相同。如果要對大量的文檔進(jìn)行排序,強(qiáng)烈建議在管道的第一個(gè)階段進(jìn)行排序,這時(shí)可以使用索引。

3.6、常見的聚合函數(shù)

1:count:用于返回集合中文檔的數(shù)量

2:distinct:找出給定鍵的所有不同值,使用時(shí)必須指定集合和鍵,例如:

db.runCommand({"distinct":"users","key":"userId"});

四、MapReduce

在MongoDB的聚合框架中,還可以使用MapReduce,它非常強(qiáng)大和靈活,但具有一定的復(fù)雜性,專門用于實(shí)現(xiàn)一些復(fù)雜的聚合功能。

MongoDB中的MapReduce使用JavaScript來作為查詢語言,因此能表達(dá)任意的邏輯,但是它運(yùn)行非常慢,不應(yīng)該用在實(shí)時(shí)的數(shù)據(jù)分析中。

4.1、MapReduce的HelloWorld

實(shí)現(xiàn)的功能,找出集合中所有的鍵,并統(tǒng)計(jì)每個(gè)鍵出現(xiàn)的次數(shù)。

1:Map函數(shù)使用emit函數(shù)來返回要處理的值,示例如下:

var map = function(){
    for(var key in this){
        emit(key,{count:1});
    }
}

this表示對當(dāng)前文檔的引用。

2:reduce函數(shù)需要處理Map階段或者是前一個(gè)reduce的數(shù)據(jù),因此reduce返回的文檔必須要能作為reduce的第二個(gè)參數(shù)的一個(gè)元素,示例如下:

var reduce = function(key,emits){
    var total = 0;
    for(var i in emits){
        total += emits[i].count;
    }
    return {"count":total};
};

3:運(yùn)行MapReduce,示例如下:

> var mr =db.runCommand({"mapreduce":"scores","map":map,"reduce":reduce,"out":"mrout"});

說明:scores是集合名,map是map函數(shù),reduce是reduce函數(shù),mrout是輸出的變量名

4:查詢最終的結(jié)果,示例如下:

db.mrout.find();

MongoDB(4): 聚合框架

還可以改變一下,比如統(tǒng)計(jì)studentId中值,以及每個(gè)值出現(xiàn)的次數(shù),就可以如下操作:

1:修改map函數(shù),示例如下:

var map = function(){
    emit(this.studentId,{count:1});
};

2:reduce函數(shù)不用改

3:重新執(zhí)行

db.runCommand({"mapreduce":"scores","map":map,"reduce":reduce,"out":"mrout"});

4:查看最終結(jié)果

db.mrout.find();

MongoDB(4): 聚合框架

4.2、更多MapReduce可選的鍵

1:finalize:function :可以將reduce的結(jié)果發(fā)送到finalize,這是整個(gè)處理的最后一步

2:keeptemp:boolean :是否在連接關(guān)閉的時(shí)候,保存臨時(shí)結(jié)果集合

3:query:document :在發(fā)送給map前對文檔進(jìn)行過濾

4:sort:document :在發(fā)送給map前對文檔進(jìn)行排序

5:limit:integer :發(fā)往map函數(shù)的文檔數(shù)量上限

6:scope:document :可以在javascript中使用的變量

7:verbose:boolean :是否記錄詳細(xì)的

MongoDB(4): 聚合框架

五、聚合命令group

用來對集合進(jìn)行分組,分組過后,再對每一個(gè)分組內(nèi)的文檔進(jìn)行聚合。

比如要對studentId進(jìn)行分組,找到每個(gè)學(xué)生最高的分?jǐn)?shù),可以如下步驟進(jìn)行:

db.runCommand({"group":{
    "ns":"scores",
    "key":{"studentId":1},
    "initial":{"score":0},
    "$reduce":function(doc,prev){
        if(doc.score > prev.score){
            prev.score = doc.score;
        }
    }
}});

ns:指定要分組的集合

key:指定分組的鍵

initial:每一組的reduce函數(shù)調(diào)用的時(shí)候,在開頭的時(shí)候調(diào)用一次,以做初始化

$reduce:在每組中的每個(gè)文檔上執(zhí)行,系統(tǒng)會(huì)自動(dòng)傳入兩個(gè)參數(shù),doc是當(dāng)前處理的文檔,prev是本組前一次執(zhí)行的結(jié)果文檔

你還可以在group的時(shí)候添加條件,就是加入condition,示例如:

db.runCommand({"group":{
    "ns":"scores",
    "key":{"studentId":1},
    "initial":{"score":0},
    "$reduce":function(doc,prev){
        if(doc.score > prev.score){
            prev.score = doc.score;
        }
    }
    ,"condition":{"studentId":{$lt:"s2"}}
}});

同樣可以使用finalizer來對reduce的結(jié)果進(jìn)行最后的處理,比如要求每個(gè)學(xué)生的平均分,就可以先按照studentId分組,求出一個(gè)總的分?jǐn)?shù)來,然后在finalizer里面,求平均分:

db.runCommand({"group":{
    "ns":"scores",
    "key":{"studentId":1},
    "initial":{"total":0},
    "$reduce":function(doc,prev){
        prev.total += doc.score;
    },
    "condition":{"studentId":{"$lt":"s2"}},
    "finalize":function(prev){
        prev.avg = prev.total/3;
    }
}});

注意:finalize是只在每組結(jié)果返回給用戶前調(diào)用一次,也就是每組結(jié)果只調(diào)用一次

對于分組的key較為復(fù)雜的時(shí)候,還可以采用函數(shù)來做為鍵,比如讓鍵不區(qū)分大小下,就可以如下定義:

db.runCommand({"group":{
    "ns":"scores",
    $keyf:function(doc){
        return {studentId:doc.studentId.toLowerCase()};
    },
    "initial":{"total":0},
    "$reduce":function(doc,prev){
        prev.total += doc.score;
    },
    "condition":{"$or":[{"studentId":{"$lt":"s2"}},{"studentId":"S0"}]},
    "finalize":function(prev){
        prev.avg = prev.total/3;
    }
}});

注意:要使用$keyf來定義函數(shù)作為鍵,另外一定要返回對象的格式

新聞標(biāo)題:MongoDB(4):聚合框架
當(dāng)前URL:http://sd-ha.com/article8/popjop.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計(jì)、、動(dòng)態(tài)網(wǎng)站、響應(yīng)式網(wǎng)站微信小程序、虛擬主機(jī)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

營銷型網(wǎng)站建設(shè)