日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無先后,達者為師

網(wǎng)站首頁 編程語言 正文

MongoDB?聚合查詢詳解_MongoDB

作者:程序員翔仔 ? 更新時間: 2023-01-31 編程語言

聚合管道

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

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

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

在這里可以看得出,aggregate([{}, {}])?是一個聚合語句,在函數(shù)的數(shù)組中,每一個對象都是一個階段,$match?應(yīng)該就是一個篩選文檔的階段,$group?應(yīng)該就是一個分組匯總的階段。

管道階段

使用聚合框架最重要的就是熟悉操作的語法,以及將這些語法構(gòu)建成管道當(dāng)中的階段。

在 MongoDB 聚合框架中,每一個階段都必須要規(guī)定一個特定的階段運算符,這些階段運算符表明了階段的執(zhí)行規(guī)則,可以到?官方文檔?上查看更多、更詳細的內(nèi)容。

常見操作

最常見的操作應(yīng)該是能與普通查詢語句對應(yīng)上的操作,如查詢、投影、排序、跳過、限制等等。雖然這些在一個?find()?語句中就能實現(xiàn)。

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

{ $match: { <query> } }

第二個則是投影,這個階段可以修改輸入文檔的結(jié)構(gòu),通常是重命名、增加、刪除屬性,也可以通過表達式創(chuàng)建計算結(jié)果以及嵌套文檔。如下是其使用語法:

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

排序、跳過、限制都比較容易理解,實際上可以與?find()?結(jié)果的游標(biāo)支持的函數(shù)做聯(lián)系。如下是其使用語法:

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

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

  • 通過篩選語句過濾指定集合,得到符合要求的文檔列表;
  • 如果排序非常重要,這一個階段需要在過濾文檔之后;
  • 如果需要做分頁功能,應(yīng)該是先執(zhí)行跳過的階段,然后再到限制的階段;
  • 最后,執(zhí)行投影階段(進入投影階段的文檔應(yīng)該盡量少)。

更多操作 - 投影

投影階段一個比較大的作用就是,限制下一步的文檔字段數(shù)量,也就是刪除屬性,如下是使用方式:

// 不返回 _id 字段
{ $project: { _id: 0 } }
// 不返回指定的 field 字段
{ $project: { <field>: 0 } }

刪除屬性是黑名單的功能,投影階段也支持白名單的功能,即返回列表內(nèi)的字段,如下是使用方式:

// 返回指定的 field 字段
{ $project: { <field>: 1 } }

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

// 將 author 嵌套文檔下 last 屬性賦值給 lastName 屬性
{ $project: { lastName: "$author.last" } }
// 上述的功能里,對于嵌套文檔和內(nèi)嵌數(shù)組返回的結(jié)果是不一樣的,數(shù)組會繼承下來
 
// 投影支持類似于三元運算的表達式
{ $project: { lastName: {
    $cond: {
        if: { $eq: [ "", "$author.last" ] },
        then: "$$REMOVE",
        else: "$author.last",
    }
} } }

更多操作 - 展開

在處理數(shù)組時,一個比較常見的操作是為數(shù)組中的每一個元素形成一個輸出文檔。

一個實際的例子就是,一件衣服在庫存中有 S、M、L 三個尺寸,而這三個尺寸會存儲在同一個數(shù)組字段當(dāng)中,當(dāng)我們聚合時想要將這一條文檔展開成三個文檔,一個尺寸對應(yīng)一個文檔。

// 原始文檔
{
    "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: {
        // 分組的標(biāo)識
        _id: <expression>,
        <field1>: { <accumulator1> : <expression1> },
        ...
    }
 }

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

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

尤其是,MongoDB 提供了累加器可以實現(xiàn)復(fù)雜的功能,如求和、平均值、最大值、最小值等等。

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

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

更多操作 - 入庫

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

聚合框架提供了?$out?和?$merge?兩個運算符標(biāo)識入庫階段,其中?$merge?是在 4.2 版本中引入的。這兩個操作符的語法如下:

// 指定數(shù)據(jù)庫和集合,會直接覆蓋
{ $out: { db: "<output-db>", coll: "<output-collection>" } }
 
// 配置更加豐富
{ $merge: {
    // 指定數(shù)據(jù)庫和集合
    into: <collection> -or- { db: <db>, coll: <collection> },
    // 確定唯一標(biāo)識與集合中做匹配
    on: <identifier field> -or- [ <identifier field1>, ...],  // Optional
    // 設(shè)定變量
    let: <variables>,                                         // Optional
    // 如果標(biāo)識存在時處理文檔的方式
    whenMatched: <replace|keepExisting|merge|fail|pipeline>,  // Optional
    // 如果標(biāo)識不存在時處理文檔的方式
    whenNotMatched: <insert|discard|fail>                     // Optional
} }

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

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

條件組累加器

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

算術(shù)運算

這里的算術(shù)運算不是統(tǒng)稱的四則運算,指的是與數(shù)學(xué)相關(guān)的運算,如平均值、求和等。

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

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

最值運算

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

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

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

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

數(shù)組提取

這里的數(shù)組提取指的是提取數(shù)組中的某個元素,現(xiàn)在能支持到的就是提取出數(shù)組中的前 n 個元素、后 n 個元素。

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

{ $first: <expression> }
 
{
    $firstN: {
        input: <expression>,
        n: <expression>
    }
}
 
{ $last: <expression> }
 
{
    $lastN: {
        input: <expression>,
        n: <expression>
    }
}

其他運算

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

  • $accumulator: 返回自定義累加器函數(shù)的結(jié)果
  • $addToSet: 返回一個無重復(fù)值的數(shù)組
  • $bottom: 返回指定排序規(guī)則后最后 1 個元素
  • $bottomN: 返回指定排序規(guī)則后最后 n 個元素
  • $count: 返回文檔的計數(shù)
  • $mergeObjects: 返回合并多個對象之后的結(jié)果
  • $push: 返回一個可以有重復(fù)值的數(shù)組
  • $stdDevPop: 返回輸入值的總體標(biāo)準(zhǔn)差
  • $stdDevSamp: 返回輸入值的樣本標(biāo)準(zhǔn)差

這些累加器都有各自的用法,使用得當(dāng)可實現(xiàn)非常強大的數(shù)據(jù)分析功能,完整的內(nèi)容可以到?官方文檔?上查看。

原文鏈接:https://www.cnblogs.com/fatedeity/p/16920756.html

欄目分類
最近更新