MongoDB的聚合筆記

銀河小船兒發表於2023-12-10

1,聚合

聚合(aggregate)主要用於計算資料,類似sql中的sum()、avg()。

          

 常用的表示式如上圖。

1.1,aggregate  語法

語法:     db.集合名稱.aggregate([{管道:{表示式}}])

 

常用的管道:

 

1.2,$match 和 $group

 

 往集合 items 中先插入資料

db.items.insert(
[
{quantity:2,price:5.0,pnumber:"p003"},
{quantity:2,price:8.0,pnumber:"p002"},
{quantity:1,price:4.0,pnumber:"p002"},
{quantity:2,price:4.0,pnumber:"p001"},
{quantity:4,price:10.0,pnumber:"p003"},
{quantity:10,price:20.0,pnumber:"p001"},
{quantity:10,price:20.0,pnumber:"p003"},
{quantity:5,price:10.0,pnumber:"p002"}
]
)

 檢視視覺化工具插入的結果如下:

 例1:

   查詢 pnumber:"p001" , 再來看語法 :db.集合名稱.aggregate([{管道:{表示式}}])

db.items.aggregate([{"$match":{"pnumber":"p001"}}])

 

例2:

 

    查詢price 大於8的 quantity ,以平均值 avg_quantity表示,並按 pnumber分組。所以分組欄位是 $pnumber,平均值avg_quantity,avg_quantity是新的欄位名,聚合運算子是 $avg。

db.items.aggregate([
   {"$match":{"price":{"$gt":8}}},
   {"$group":{"_id":"$pnumber","avg_quantity":{"$avg":"$quantity"}}}
])

 

例3:

    查詢 price大於8的quantity,以平均值 avg_quantity 表示,並過濾出平均值大於5的avg_quantity。前半句話是上個例子的,過濾出 是用 $match。

db.items.aggregate([
   {"$match":{"price":{"$gt":8}}},
   {"$group":{"_id":"$pnumber","avg_quantity":{"$avg":"$quantity"}}},
   {"$match":{"avg_quantity":{"$gt":5}}}
])

 

例4:

   按 pnumber分組

db.items.aggregate([
      {"$group":{"_id":"$pnumber"}}   
])

   按 quantity 和 price 分組

db.items.aggregate([
      {"$group":{"_id":{"quantity":"$quantity","price":"$price"}}}   
])

  截了部分屏

 

 1.3,聚合運算子($sum,$avg,$max,$min,$first,$last)

例1($max):

   按 pnumber 分組,並求出 每組 price的最大值max_price

db.items.aggregate([
      {"$group":
          {"_id":"$pnumber",
           "max_price":{"$max":"$price"}
           }
       }   
])

 

例2($min):

   按 pnumber分組,並求出每組 price 的最大值 max_price,最小值 min_price

db.items.aggregate([
      {"$group":
          {"_id":"$pnumber",
           "max_price":{"$max":"$price"},
           "min_price":{"$min":"$price"}
           }
       }   
])

 

 

 這個把上面寫的 $max,$min一替換就行。

 

 例3($sum):

    按pnumber分組,並計算每組的 quantity的總和 count,並按count升序排。這裡用了 $sort,注意要在分組完才能 $sort(看好格式)。

db.items.aggregate([
      {"$group":
          {"_id":"$pnumber","count":{"$sum":"$quantity"}},
       },
       {"$sort":{"count": 1}}   
])

 

 例4:

     查詢分組後 每個 pnumber 出現的次數,並按升序排

db.items.aggregate([
      {"$group":
          {"_id":"$pnumber","count":{"$sum":1}},
       },
       {"$sort":{"count": 1}}   
])

 

 例5($addToSet,$push):

    按 pnumber 分組,並查出各 pnumber內的price ,price可以重複 (用 $push)

db.items.aggregate([
      {"$group":
               {"_id":"$pnumber","prices":{"$push":"$price"}}             
       }
])

  結果 是因為新增的資料不太好,所以看不出有沒有重複還是重複了。

   按 pnumber 分組,並查出各 pnumber內的price ,price不可以重複 (用 $addToSet)

db.items.aggregate([
      {"$group":
               {"_id":"$pnumber","prices":{"$addToSet":"$price"}}             
       }
])

 

 

 1.4,投射 ($project),$add

     只保留 _id 和 pnumber,新增 new_price,new_price 就是讓 price加1(用到了 $add)

db.items.aggregate([
      {
          $project:{
              "_id":1,
              "pnumber":1,
              "new_price":{"$add":["$price", 1]}
                    }
       }
])

 

 

 1.5,排序($sort),限制($limit),跳過($skip)

 

 例1:

    取平均價格最貴的前兩個pnumber,所以是按pnumber分組($group),再降序排($sort),再限制是前兩個($limit)。

db.items.aggregate([
    {
        "$group":{"_id":"$pnumber","平均價格":{"$avg":"$price"}}   
    },
    {
        "$sort":{"平均價格": -1}
    },
    {
        "$limit": 2
    }  
])

 

 例2:

      取平均價格最貴的第二個 pnumber,就是在上個例子的基礎上,跳過1個, $skip:1

db.items.aggregate([
    {
        "$group":{"_id":"$pnumber","平均價格":{"$avg":"$price"}}   
    },
    {
        "$sort":{"平均價格": -1}
    },
    {
        "$limit": 2
    },
    {
        "$skip":1
    }  
])

 

 1.6,隨機獲取,$sample

db.items.aggregate([
     {$sample: {size: 3}}
])

   再點執行,就出來不一樣的結果

 

 1.7,擷取($substr),拼接($concat),轉小寫($toLower),轉大寫($toUpper)

 

 例1:

   把 pnumber 的下標為 0到2 位置的 截出來,_id 隱藏

db.items.aggregate([
    {
      $project:{
         "_id":0,
         "str": {$substr: ["$pnumber", 0, 2]}
                }  
    }

])

   因為擷取是 左閉右開的截,所以顯示是兩個字元。

 

 例2:

    把 pnumber 欄位下的內容 和 "測試" 拼接起來

db.items.aggregate([
    {
      "$project":{
         "_id":0,
         "str": {"$concat": ["$pnumber", "測試"]}
                }  
    }
])

 

例3:

    將pnumber的 英文轉換為大寫

db.items.aggregate([
     {
         "$project":{"pnumber":{"$toUpper":"$pnumber"}}
     }
])

 

相關文章