MongoDB Aggregation 的 $count $sortByCount

本篇資料庫的資料依舊使用上一篇文章的範例,沒有的可以新增一下。

1
2
3
4
5
6
7
db.getCollection('movie').insertMany([
{"name": "movieA", "language": "en-gb", "rating": 8, "totalCost": 30000000, "producer": "companyA"},
{"name": "movieB", "language": "en-gb", "rating": 5, "totalCost": 10000000, "producer": "companyA"},
{"name": "movieC", "language": "zh-tw", "rating": 6, "totalCost": 25000000, "producer": "companyA"},
{"name": "movieD", "language": "zh-tw", "rating": 8, "totalCost": 10000000, "producer": "companyB"},
{"name": "movieE", "language": "zh-tw", "rating": 9, "totalCost": 6000000, "producer": "companyC"},
])

$count

這邊要介紹的 $count 是在 aggregation 階段使用的,跟在 5.0 後 group 內使用的又有點語法不同。

  • Aggregation 版本
1
2
3
4
db.movie.aggregate([
{ $match: { rating: { $gt: 7 } } },
{ $count: "popular_movie" }
])
  • Group 版本 (5.0之前)
1
2
3
4
5
db.movie.aggregate( [
{ $match: { rating: { $gt: 7 } } },
{ $group: { _id: null, rating: { $sum: 1 } } },
{ $project: { _id: 0 } }
] )
  • Group 版本 (5.0之後)
1
2
3
4
5
db.movie.aggregate( [
{ $match: { rating: { $gt: 7 } } },
{ $group: { _id: null, rating: { $count: {} } } },
{ $project: { _id: 0 } }
] )

5.0 之後可以直接使用 $count: {} 語法算出數量,且可以直接命名欄位,不用新增 project,另外要注意的是這樣寫,$count: {} 是不能帶任何參數的。

Count 功能其實還有 db.collection.count()db.collection.countDocuments(),但這是屬於 mongosh 的語法,各個語言的 driver 支援程度也不同,像是 c# 就是有支援,使用前還是需要查一下。

`Murmur: 我覺得各種語言,甚至 mongo 自己都搞得太多種類,太複雜了。

$sortByCount

sortByCount 使用情境就相對單純一點,顧名思義,按照統計的數量來 倒序 顯示,而預設的 _id 則為該欄位的數值。

1
2
3
4
db.movie.aggregate( [
{ $match: { } } ,
{ $sortByCount: "$producer" }
] )

結果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* 1 */
{
"_id" : "companyA",
"count" : 3
}

/* 2 */
{
"_id" : "companyB",
"count" : 1
}

/* 3 */
{
"_id" : "companyC",
"count" : 1
}

可以看到我們針對 producer 欄位進行 sortByCount,會直接做 group & count 的動作。


今天介紹的兩個比較常用的計算語法,唯獨要注意的是計算的資料筆數和大小不要超過 MongoDB 的限制(印象好像是 16MB),超過就無法使用了,因此聚合前期的過濾很重要,務必減少範圍且挑選必要的欄位就好。