256_Mongodb_聚合操作
聚合操作
MongoDB的聚合操作是通過數(shù)據(jù)處理管道(pipeline)來實現(xiàn)的,一次操作可以通過多個管道來處理,且管道是有順序的
聚合操作可用于實現(xiàn)分組, 排序, 數(shù)值運算, 條件篩選,多表關(guān)聯(lián)查詢等
聚合管道包含非常豐富的聚合階段,下面是最常用的聚合階段
階段
描述
$group
分組
$project
顯示字段
$match
篩選條件
$sort/$skip/$limit
排序分頁
$lookup
多表關(guān)聯(lián)
$unwind
展開數(shù)組
$out
結(jié)果匯入新表
$count
文檔計數(shù)
$project:修改輸入文檔的結(jié)構(gòu)。可以用來重命名、增加或刪除域,也可以用于創(chuàng)建計算結(jié)果以及嵌套文檔。 $match:用于過濾數(shù)據(jù),只輸出符合條件的文檔。$match使用MongoDB的標(biāo)準(zhǔn)查詢操作。 $limit:用來限制MongoDB聚合管道返回的文檔數(shù)。 $skip:在聚合管道中跳過指定數(shù)量的文檔,并返回余下的文檔。 $unwind:將文檔中的某一個數(shù)組類型字段拆分成多條,每條包含數(shù)組中的一個值。 $group:將集合中的文檔分組,可用于統(tǒng)計結(jié)果。 $sort:將輸入文檔排序后輸出。 $geoNear:輸出接近某一地理位置的有序文檔
語法格式
db.collection.aggregate([ {pipeline_1}, {pipeline_2} …. ])
1 聚合-$group
$group 聚合操作符主要作用是對文檔中特定字段進行分組,搭配下面的操作符對結(jié)果進行計算
操作符
說明
$sum
利用$group分組后,對同組的文檔進行 計算總和
$avg
利用$group分組后,對同組的文檔進行 計算平均值
$min
利用$group分組后,對同組的文檔進行 獲取集合中所有文檔對應(yīng)值得最小值。
$max
利用$group分組后,對同組的文檔進行 獲取集合中所有文檔對應(yīng)值得最大值。
$push
利用$group分組后,對同組的文檔進行 以數(shù)組的方式顯示指定的字段
$addToSet
將值加入一個數(shù)組中,會判斷是否有重復(fù)的值,以數(shù)組的方式顯示字段不重復(fù)的值
$first
根據(jù)資源文檔的排序獲取第一個文檔數(shù)據(jù)。
$last
根據(jù)資源文檔的排序獲取最后一個文檔數(shù)據(jù)
db.sales.drop() db.sales.insertMany([ { "_id" : 1, "item" : "abc", "price" : NumberDecimal("10"), "quantity" : NumberInt("2"), "date" : ISODate("2014-03-01T08:00:00Z") }, { "_id" : 2, "item" : "jkl", "price" : NumberDecimal("20"), "quantity" : NumberInt("1"), "date" : ISODate("2014-03-01T09:00:00Z") }, { "_id" : 3, "item" : "xyz", "price" : NumberDecimal("5"), "quantity" : NumberInt( "10"), "date" : ISODate("2014-03-15T09:00:00Z") }, { "_id" : 4, "item" : "xyz", "price" : NumberDecimal("5"), "quantity" : NumberInt("20") , "date" : ISODate("2014-04-04T11:21:39.736Z") }, { "_id" : 5, "item" : "abc", "price" : NumberDecimal("10"), "quantity" : NumberInt("10") , "date" : ISODate("2014-04-04T21:23:13.331Z") }, { "_id" : 6, "item" : "def", "price" : NumberDecimal("7.5"), "quantity": NumberInt("5" ) , "date" : ISODate("2015-06-04T05:08:13Z") }, { "_id" : 7, "item" : "def", "price" : NumberDecimal("7.5"), "quantity": NumberInt("10") , "date" : ISODate("2015-09-10T08:43:00Z") }, { "_id" : 8, "item" : "abc", "price" : NumberDecimal("10"), "quantity" : NumberInt("5" ) , "date" : ISODate("2016-02-06T20:20:13Z") }, ]) db.sales.find()
語法格式
>db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION) db.collection.aggregate( [{ $group: {"_id": "$<分組字段名稱>",<顯示結(jié)果的名稱>:{<操作符>: "$<計算的字段>"}} } ]) # select item, count( quantity ) from sales group by item db.sales.aggregate( [{$group:{"_id" : "$item", "sum":{$sum :"$quantity"} } } ]) db.sales.aggregate([{$group: {"_id": null, "count":{$sum: 1}}}]) //8 db.sales.find().size()
2 顯示字段 $project
文檔字段較多, 只想查詢幾個字段, 將預(yù)顯示的字段設(shè)定為 “1”;? 其余字段默認(rèn)不顯示(也可以設(shè)置為”0”), “_id” 較為特別, 默認(rèn)顯示
# 常規(guī)顯示操作 db.sales.aggregate({"$project": {"_id":0, "item":1}}) # 搭配其他操作符 語法 db.collection.aggrate([ { $project: { <顯示結(jié)果的名稱1>:{<操作符1> : <操作符條件2>}。 <顯示結(jié)果的名稱2>:{<操作符2>:<操作符條件2>} } } ]) # $substr 需要三個參數(shù):字符串, 起始參數(shù)(0 代表第一個字符), 長度參數(shù)(如為負表示截取到結(jié)尾) db.sales.aggregate({"$project": {"_id":0, "item_xxxx": {$substr: ["$item", 0,1]}}}) # $switch 對指定字段進行一系列條件判斷,符合則返回 db.sales.aggregate({[{"$project": {"priceSwitch": {$switch: {branches: [ {case: {$gt: ["$price", 5], then: "price>5"}}, {case: {$lt: ["$price", 10], then: "price<10"}}], default:"price <=5 & price >=10"}} } }])
3 數(shù)據(jù)排序/跳過限制文檔數(shù)量 $sort $skip $limit
需要對報表進行分頁, 將”$sort” “skip” “$limit” 一起使用
操作符
說明
$sort
升序 1 降序 -1
$skip
顯示文檔時 跳過只讀數(shù)量的文檔
$limit
限制顯示的文檔數(shù)量
/* SELECT date, Sum(( price * quantity )) AS totalSaleAmount, Avg(quantity) AS averageQuantity, Count(*) AS Count FROM sales GROUP BY Date(date) ORDER BY totalSaleAmount DESC */ db.sales.aggregate([ // First Stage { $match : { "date": { $gte: new ISODate("2014-01-01"), $lt: new ISODate("2015-01-01") } } }, // Second Stage { $group : { _id : { $dateToString: { format: "%Y-%m-%d", date: "$date" } }, totalSaleAmount: { $sum: { $multiply: [ "$price", "$quantity" ] } }, averageQuantity: { $avg: "$quantity" }, count: { $sum: 1 } } }, // Third Stage { $sort : { totalSaleAmount: -1 } } ])
5 多表關(guān)聯(lián)查詢 $lookup
找出集合中與另一個集合條件匹配的文檔, 類似關(guān)系型數(shù)據(jù)庫的join
From 需要關(guān)聯(lián)另一個集合, localField: 集合中需關(guān)聯(lián)的鍵, foreignField 與另一個集合關(guān)聯(lián)的鍵 As 關(guān)聯(lián)后另外一個集合的數(shù)據(jù)嵌入至此字段下 db.orders.drop() db.orders.insert([ { "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2 }, { "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1 }, { "_id" : 3 } ]) // $lookup,多表關(guān)聯(lián) /* SELECT *, inventory_docs FROM orders WHERE inventory_docs IN ( SELECT * FROM inventory WHERE sku= orders.item ); */ db.orders.aggregate([ { $lookup: { from: "inventory", localField: "item", foreignField: "sku", as: "inventory_docs" } } ])
6? 計算文檔數(shù)量 $count
db.inventory.aggregate([{$match:{"qty":{$gte:50}}},{$count: "qty_count"}])
7? 展開數(shù)組 $unwind
將文檔中數(shù)組形式的數(shù)據(jù)拆分成數(shù)個文檔,如指定字段不存在,則不會進行拆分
語法 db.collecton.aggregate([ {$unwind: {path:
db.inventory.aggregate( [ { $unwind: { path: "$tags", preserveNullAndEmptyArrays: true } }, { $group: { _id: "$tags", averageQty: { $avg: "$qty" } } }, { $sort: { "averageQty": -1 } }, { $skip: 2}, { $limit: 2} ] )
8 $out
將聚合出來的結(jié)果寫入一個指定的集合中,如果原集合中有索引,寫入的文檔違反索引,則寫入失敗
// $out,將聚合結(jié)果匯入新表 db.inventory.aggregate( [ // First Stage { $unwind: { path: "$tags", preserveNullAndEmptyArrays: true } }, // Second Stage { $group: { _id: "$tags", averageQty: { $avg: "$qty" } } }, // Third Stage { $sort: { "averageQty": -1 } }, { $out : "tagsAvgQty" } ] ) db.tagsAvgQty.find();
MapReduce
MapReduce操作具有兩個階段:處理每個文檔并向每個輸入文檔發(fā)射一個或多個對象的map階 段,以及reduce組合map操作的輸出的階段。
Map 通過鍵值對形式 將相同 key 的文檔 保存到 value 數(shù)組中,把結(jié)果集key value輸出給 reduce階段
Reduce 根據(jù) key 對value 進行計算,然后再輸出
語法 db.collection.mapreduce(
db.inventory.find().size() db.inventory.find() // 示例 var mapFun = function() { // 類似hashmap的put方法,不一樣的地方在于同一個Key不是替換,而是追加 emit(this.status, this.qty); }; var reduceFun = function(keyCustId, valuesQty) { return Array.sum(valuesQty); }; db.inventory.mapReduce( mapFun, reduceFun, { out: "map_reduce_inventory" } ) db.map_reduce_inventory.find()
MongoDB 數(shù)據(jù)結(jié)構(gòu)
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。