主頁 > 資料庫 > MongoDB - 聚合查詢

MongoDB - 聚合查詢

2022-11-25 07:18:55 資料庫

聚合管道

聚合框架是 MongoDB 中的一組分析工具,可以對一個或多個集合中的檔案進行分析,

MongoDB 的聚合框架基于管道的概念:首先從集合中獲取到輸入,然后將輸入的檔案傳遞到一個或多個階段,每個階段都將之前階段輸出的內容作為輸入,最終得到一個聚合結果作為輸出,

聚合管道

上面的圖是一個比較寬泛的管道流程圖,這里展示一個 MongoDB 聚合陳述句映射到管道之后的情況:

聚合流程圖示

在這里可以看得出,aggregate([{}, {}]) 是一個聚合陳述句,在函式的陣列中,每一個物件都是一個階段,$match 應該就是一個篩選檔案的階段,$group 應該就是一個分組匯總的階段,

管道階段

使用聚合框架最重要的就是熟悉操作的語法,以及將這些語法構建成管道當中的階段,

在 MongoDB 聚合框架中,每一個階段都必須要規定一個特定的階段運算子,這些階段運算子表明了階段的執行規則,可以到 官方檔案 上查看更多、更詳細的內容,

常見操作

最常見的操作應該是能與普通查詢陳述句對應上的操作,如查詢、投影、排序、跳過、限制等等,雖然這些在一個 find() 陳述句中就能實作,

最常使用的操作就是查詢,也可以說是篩選、過濾,在聚合框架中使用 $match 來表明這是一個篩選檔案的階段,如下是其使用語法:

{ $match: { <query> } }

第二個則是投影,這個階段可以修改輸入檔案的結構,通常是重命名、增加、洗掉屬性,也可以通過運算式創建計算結果以及嵌套檔案,如下是其使用語法:

// <field>: <1 or true>
// <field>: <0 or false>
// <field>: <expression>
{ $project: { <specification(s)> } }

排序、跳過、限制都比較容易理解,實際上可以與 find() 結果的游標支持的函式做聯系,如下是其使用語法:

// 排序
{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }
// 跳過
{ $skip: <positive 64-bit integer> }
// 限制
{ $limit: <positive 64-bit integer> }

上述 5 個階段是最常用的階段,在使用時需要注重它們的效率,一般會使用這樣的順序去構建管道:

  1. 通過篩選陳述句過濾指定集合,得到符合要求的檔案串列;
  2. 如果排序非常重要,這一個階段需要在過濾檔案之后;
  3. 如果需要做分頁功能,應該是先執行跳過的階段,然后再到限制的階段;
  4. 最后,執行投影階段(進入投影階段的檔案應該盡量少),

更多操作 - 投影

投影階段一個比較大的作用就是,限制下一步的檔案欄位數量,也就是洗掉屬性,如下是使用方式:

// 不回傳 _id 欄位
{ $project: { _id: 0 } }
// 不回傳指定的 field 欄位
{ $project: { <field>: 0 } }

洗掉屬性是黑名單的功能,投影階段也支持白名單的功能,即回傳串列內的欄位,如下是使用方式:

// 回傳指定的 field 欄位
{ $project: { <field>: 1 } }

前兩個功能是比較好理解的,但投影階段所能做的遠不止如此,還有很多其他的功能(投影階段支持大部分條件組),這里做個簡單舉例:

// 將 author 嵌套檔案下 last 屬性賦值給 lastName 屬性
{ $project: { lastName: "$author.last" } }
// 上述的功能里,對于嵌套檔案和內嵌陣列回傳的結果是不一樣的,陣列會繼承下來

// 投影支持類似于三元運算的運算式
{ $project: { lastName: {
    $cond: {
        if: { $eq: [ "", "$author.last" ] },
        then: "$$REMOVE",
        else: "$author.last",
    }
} } }

更多操作 - 展開

在處理陣列時,一個比較常見的操作是為陣列中的每一個元素形成一個輸出檔案,

一個實際的例子就是,一件衣服在庫存中有 S、M、L 三個尺寸,而這三個尺寸會存盤在同一個陣列欄位當中,當我們聚合時想要將這一條檔案展開成三個檔案,一個尺寸對應一個檔案,

// 原始檔案
{
    "clothesId": "123456",
    "sizeList": ["S", "M", "L"]
}

// 展開后的檔案
{
    "clothesId": "123456",
    "sizeList": "S"
}
{
    "clothesId": "123456",
    "sizeList": "M"
}
{
    "clothesId": "123456",
    "sizeList": "L"
}

聚合程序中,展開階段的語法是:

{ $unwind: <field path> }
// 上述衣服的例子中,可以用以下陳述句來展開
{ $unwind: "$sizeList" }

更多操作 - 分組

分組是聚合管道中舉足輕重的一個階段,這里的分組可以看作是 SQL 的 GOURP BY 陳述句,其能為聚合功能帶來非常大的可能性,

分組階段使用了 $group 運算子,支持使用一個鍵或多個鍵將輸入的檔案進行分組,其語法如下:

{
    $group: {
        // 分組的標識
        _id: <expression>,
        <field1>: { <accumulator1> : <expression1> },
        ...
    }
 }

其中 _id 是必須的,可以簡單指定分組的鍵,也可以使用條件組做處理后生成自定義鍵,

可選的 <field> 是分組后需要展示的鍵,并且可以指定條件組來決定它們的值是什么,

尤其是,MongoDB 提供了累加器可以實作復雜的功能,如求和、平均值、最大值、最小值等等,

這里有個對集合求和的例子,也是最簡單的使用:

{
    $group: {
        // 對型別進行分組
        _id: "type",
        // 這里是求和,一個檔案記作 1 個,即對同型別的檔案進行計數
        count: { $sum: 1 },
    }
 }

更多操作 - 入庫

顧名思義,入庫需要作為管道中最后的階段,將管道生成的檔案寫入集合中,

聚合框架提供了 $out$merge 兩個運算子標識入庫階段,其中 $merge 是在 4.2 版本中引入的,這兩個運算子的語法如下:

// 指定資料庫和集合,會直接覆寫
{ $out: { db: "<output-db>", coll: "<output-collection>" } }

// 配置更加豐富
{ $merge: {
    // 指定資料庫和集合
    into: <collection> -or- { db: <db>, coll: <collection> },
    // 確定唯一標識與集合中做匹配
    on: <identifier field> -or- [ <identifier field1>, ...],  // Optional
    // 設定變數
    let: <variables>,                                         // Optional
    // 如果標識存在時處理檔案的方式
    whenMatched: <replace|keepExisting|merge|fail|pipeline>,  // Optional
    // 如果標識不存在時處理檔案的方式
    whenNotMatched: <insert|discard|fail>                     // Optional
} }

如果可以的話,建議使用 $merge 作為寫入集合的首選方式,其功能更多,

當然,其真正的優勢是,可以按照按需生成的物化視圖(materialized view),在管道運行的階段,輸出到集合的內容會進行增量更新,

條件組累加器

在一些階段操作中,MongoDB 支持使用累加器來增強聚合功能,這里說的累加器泛指求和、平均值、最大值、最小值等功能的運算子,

算術運算

這里的算術運算不是統稱的四則運算,指的是與數學相關的運算,如平均值、求和等,

$avg 累加器用于計算平均值,通過是直接指定一個鍵名即可,使用 { $avg: "$keyName" } 這樣的語法,

$sum 累加器用于計算指定鍵的和,也是直接指定一個鍵名即可,使用 { $sum: "$keyName" } 這樣的語法,

最值運算

累加器支持的最值包括這些:最小值、最大值、最大的 n 個值,

最小值和最大值的理解都比較容易,使用也比較容易,最小值使用了 { $min: "$keyName" } 這樣的語法,最大值使用了 { $max: "$keyName" } 這樣的語法,

最大的 n 個值是在 5.2 版本新增的累加器,其作用是通過指定輸入的鍵,得到這些鍵值中排序后最大的 n 個值,其語法如下:

{
    $maxN: {
        // 指定鍵名  input: "$score"
        input: <expression>,
        // 指定數量  n: 3
        n: <expression>
    }
}

陣列提取

這里的陣列提取指的是提取陣列中的某個元素,現在能支持到的就是提取出陣列中的前 n 個元素、后 n 個元素,

在這里可以使用 $first$firstN$last$lastN 這樣的運算子,它們的語法分別如下:

{ $first: <expression> }

{
    $firstN: {
        input: <expression>,
        n: <expression>
    }
}

{ $last: <expression> }

{
    $lastN: {
        input: <expression>,
        n: <expression>
    }
}

其他運算

除了上述的累加器,聚合框架還有非常多其他的累加器,這里簡單列一下:

  • $accumulator: 回傳自定義累加器函式的結果
  • $addToSet: 回傳一個無重復值的陣列
  • $bottom: 回傳指定排序規則后最后 1 個元素
  • $bottomN: 回傳指定排序規則后最后 n 個元素
  • $count: 回傳檔案的計數
  • $mergeObjects: 回傳合并多個物件之后的結果
  • $push: 回傳一個可以有重復值的陣列
  • $stdDevPop: 回傳輸入值的總體標準差
  • $stdDevSamp: 回傳輸入值的樣本標準差

這些累加器都有各自的用法,使用得當可實作非常強大的資料分析功能,完整的內容可以到 官方檔案 上查看,

首發于「程式員翔仔」,點擊查看更多,

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/538261.html

標籤:NoSQL

上一篇:MySQL資料庫:6、約束的概述及語法

下一篇:MongoDB - 聚合查詢

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:33:24 more
  • MySQL中binlog備份腳本分享

    關于MySQL的二進制日志(binlog),我們都知道二進制日志(binlog)非常重要,尤其當你需要point to point災難恢復的時侯,所以我們要對其進行備份。關于二進制日志(binlog)的備份,可以基于flush logs方式先切換binlog,然后拷貝&壓縮到到遠程服務器或本地服務器 ......

    uj5u.com 2023-04-20 08:28:06 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:27:27 more
  • 快取與資料庫雙寫一致性幾種策略分析

    本文將對幾種快取與資料庫保證資料一致性的使用方式進行分析。為保證高并發性能,以下分析場景不考慮執行的原子性及加鎖等強一致性要求的場景,僅追求最終一致性。 ......

    uj5u.com 2023-04-20 08:26:48 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:26:35 more
  • 云時代,MySQL到ClickHouse資料同步產品對比推薦

    ClickHouse 在執行分析查詢時的速度優勢很好的彌補了MySQL的不足,但是對于很多開發者和DBA來說,如何將MySQL穩定、高效、簡單的同步到 ClickHouse 卻很困難。本文對比了 NineData、MaterializeMySQL(ClickHouse自帶)、Bifrost 三款產品... ......

    uj5u.com 2023-04-20 08:26:29 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:25:13 more
  • Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)

    Redis 報錯“OutOfDirectMemoryError(堆外記憶體溢位) ”問題如下: 一、報錯資訊: 使用 Redis 的業務介面 ,產生 OutOfDirectMemoryError(堆外記憶體溢位),如圖: 格式化后的報錯資訊: { "timestamp": "2023-04-17 22: ......

    uj5u.com 2023-04-20 08:24:54 more
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:24:03 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:23:11 more