Chương này giới thiệu một giải thích chi tiết về phân tích thống kê MongoDB, chủ yếu được thực hiện thông qua Ống dẫn Tập lệnh. Nó tương tự như câu lệnh "group by" trong SQL. Trong tập lệnh MongoDB, phân tích thống kê được thực hiện bằng cách sử dụng hàm db.collection.aggregate()
.
Hướng dẫn tiên quyết
Ống dẫn Tập lệnh Tập lệnh MongoDB
Bước tổng quát
- Sử dụng
$match
để lọc dữ liệu mục tiêu - Sử dụng
$group
để nhóm và tính toán dữ liệu - Sử dụng
$sort
để sắp xếp kết quả (tùy chọn)
Dữ liệu Kiểm tra
Dữ liệu trong bộ sưu tập orders
như sau
{ _id: 1, cust_id: "abc1", ord_date: ISODate("2012-11-02T17:04:11.102Z"), status: "A", amount: 50 }
{ _id: 2, cust_id: "xyz1", ord_date: ISODate("2013-10-01T17:04:11.102Z"), status: "A", amount: 100 }
{ _id: 3, cust_id: "xyz1", ord_date: ISODate("2013-10-12T17:04:11.102Z"), status: "D", amount: 25 }
{ _id: 4, cust_id: "xyz1", ord_date: ISODate("2013-10-11T17:04:11.102Z"), status: "D", amount: 125 }
{ _id: 5, cust_id: "abc1", ord_date: ISODate("2013-11-12T17:04:11.102Z"), status: "A", amount: 25 }
Hàm tổng hợp
db.collection.aggregate(pipeline)
Giải thích:
-
pipeline
nhận một tham số mảng, trong đó mỗi phần tử đại diện cho một bước xử lý.
Ví dụ
db.orders.aggregate([
{ $match: { status: "A" } }, // Bước đầu tiên
{ $group: { _id: "$cust_id", total: { $sum: "$amount" } } }, // Bước thứ hai
{ $sort: { total: -1 } } // Bước thứ ba
])
Tương đương SQL
select sum(amount) as total from orders
where status="A"
group by cust_id
order by total desc
Bước $match
Định dạng:
{ $match: { <query> } }
Giải thích:
-
<query>
Điều kiện truy vấn MongoDB
Được sử dụng để thiết lập các điều kiện truy vấn. Nếu bỏ qua $match
, nó ngụ ý truy vấn tất cả dữ liệu.
Mẹo: Nếu bạn không quen với cú pháp truy vấn MongoDB, vui lòng tham khảo các chương trước đó.
Bước $group
Tương tự như mệnh đề group by
trong SQL, nó được sử dụng để nhóm dữ liệu và sau đó thực hiện một loạt các phép tính thống kê trên dữ liệu đã nhóm.
Sử dụng Cơ bản của $group
Cú pháp:
{
$group:
{
_id: <biểu thức>, // Điều kiện nhóm, ví dụ: nhóm theo trường nào
<field1>: { <accumulator1> : <biểu thức1> }, // Phép toán tổng hợp, bạn có thể thêm N phép toán tổng hợp
...
}
}
Giải thích:
-
- Tên chỉ số thống kê tùy chỉnh, có thể là N tổng cộng -
- Hàm tổng hợp, tương tự như tổng, trung bình và các hàm tổng hợp khác trong SQL, khác biệt là các hàm tổng hợp của MongoDB được đặt tên với $ ở tiền tố, ví dụ: $sum, $avg - <biểu thức1> - Tham số của hàm tổng hợp, thường là giá trị trường cần đếm, trích dẫn trường tài liệu bằng định dạng "$tên trường"
Ví dụ:
db.orders.aggregate([
{
$group: {
_id: "$cust_id",
total: { $sum: "$amount" }, // Thêm chỉ số thống kê đầu tiên total, sử dụng $sum toán tử tổng cộng
amount_avg: {$avg: "$amount"} // Thêm chỉ số thống kê thứ hai avg, sử dụng $avg toán tử tính trung bình
}
}
])
Kết quả:
{ "_id" : "abc1", "total" : 75, "amount_avg" : 37.5 }
{ "_id" : "xyz1", "total" : 250, "amount_avg" : 83.33333333333333 }
Tương đương SQL:
select
sum(amount) as total,
avg(amount) as amount_avg
from orders
group by cust_id
Các hàm Tính Tổng nhóm $group
Các hàm tính tổng thường được sử dụng cho $group như sau:
Toán tử | Mô tả | Ví dụ |
---|---|---|
$avg | Tính trung bình | {$avg: "$amount"} |
$sum | Tính tổng | {$sum: "$amount"} |
$max | Giá trị lớn nhất | {$max: "$amount"} |
$min | Giá trị nhỏ nhất | {$min: "$amount"} |
$first | Trả về dữ liệu sau khi nhóm, nội dung của tài liệu đầu tiên | {$first: "$amount"} |
$last | Trả về dữ liệu sau khi nhóm, nội dung của tài liệu cuối cùng | {$last: "$amount"} |
$push | Trả về dữ liệu sau khi nhóm | { $push: { ord_date: "$ord_date", amount: "$amount" } |
$addToSet | Trả về dữ liệu sau khi nhóm, khác biệt $push vì nó loại bỏ các bản sao | { $addToSet: "$amount" } |
Ví dụ về $push
db.orders.aggregate(
[
{
$group:
{
_id: "$cust_id",
all: { $push: { ord_date: "$ord_date", amount: "$amount" } } // Giá trị của trường ord_date và amount
}
}
]
)
Kết quả
{ "_id" : "abc1", "all" : [ { "ord_date" : "2021-04-18 00:00:00", "amount" : 50 }, { "ord_date" : "2021-04-21 00:00:00", "amount" : 25 } ] }
{ "_id" : "xyz1", "all" : [ { "ord_date" : "2021-04-18 00:00:00", "amount" : 100 }, { "ord_date" : "2021-04-20 00:00:00", "amount" : 25 }, { "ord_date" : "2021-04-21 00:00:00", "amount" : 125 } ] }
Ví dụ về $addToSet
db.orders.aggregate(
[
{
$group:
{
_id: "$cust_id",
all_amount: { $addToSet: "$amount" } // Trả về tất cả các giá trị amount phân biệt
}
}
]
)
Kết quả
{ "_id" : "abc1", "all_amount" : [ 25, 50 ] }
{ "_id" : "xyz1", "all_amount" : [ 100, 25, 125 ] }
$sort:
Các giai đoạn $sort thường được đặt ở cuối để sắp xếp dữ liệu đã nhóm.
Định dạng:
{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }
Giải thích:
-
, - Tên các trường cần sắp xếp, hỗ trợ nhiều trường. -
- Hướng của việc sắp xếp, -1 cho giảm dần, 1 cho tăng dần.
Ví dụ:
db.orders.aggregate([
{ $match: { status: "A" } },
{ $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
{ $sort: { total: -1 } }
])
Phân trang Tổng hợp
Chúng ta có thể thực hiện phân trang bằng cách sử dụng các toán tử $limit và $skip.
Ví dụ:
db.orders.aggregate([
{ $match: { status: "A" } },
{ $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
{ $sort: { total: -1 } },
{ $limit: 5 }, // Giới hạn số bản ghi trả về, tương tự như kích thước trang trong phân trang.
{ $skip: 1 } // Bỏ qua một số bản ghi, tương tự như độ lệch trong SQL.
])