hocvietcode.com
  • Trang chủ
  • Học lập trình
    • Lập trình C/C++
    • Cấu trúc dữ liệu và giải thuật
    • Lập trình HTML
    • Lập trình Javascript
      • Javascript cơ bản
      • ReactJS framework
      • AngularJS framework
      • Typescript cơ bản
      • Angular
    • Lập trình Mobile
      • Lập Trình Dart Cơ Bản
        • Dart Flutter Framework
    • Cơ sở dữ liệu
      • MySQL – MariaDB
      • Micrsoft SQL Server
      • Extensible Markup Language (XML)
      • JSON
      • MongoDB
    • Lập trình PHP
      • Lập trình PHP cơ bản
      • Laravel Framework
    • Lập trình Java
      • Java Cơ bản
    • Lập trình C#
      • Lập Trình C# Cơ Bản
      • ASP.NET Core MVC
    • Machine Learning
    • Git và Github
  • WORDPRESS
    • WordPress cơ bản
    • WordPress nâng cao
    • Chia sẻ WordPress
  • Kiến thức hệ thống
    • Microsoft Azure
    • Docker
    • Linux
  • Chia sẻ IT
    • Tin học văn phòng
      • Microsoft Word
      • Microsoft Excel
    • Marketing
      • Google Adwords
      • Facebook Ads
      • Kiến thức khác
    • Chia sẻ phần mềm
    • Review công nghệ
    • Công cụ – tiện ích
      • Kiểm tra bàn phím online
      • Kiểm tra webcam online
Đăng nhập
  • Đăng nhập / Đăng ký

Please enter key search to display results.

Home
  • MongoDB
Aggregation Pipeline – Các pipeline tổng hợp

Aggregation Pipeline – Các pipeline tổng hợp

  • 09-03-2026
  • Toanngo92
  • 0 Comments

Trong buổi học này, chúng ta sẽ tìm hiểu:

  • Giải thích Aggregation Pipeline trong MongoDB
  • Mô tả các giai đoạn (stages) trong aggregation pipeline
  • Giải thích các biểu thức (expressions) có thể sử dụng trong aggregation pipeline

Aggregation trong MongoDB giúp nhóm nhiều document lại với nhau, áp dụng một số thao tác xử lý và trả về một kết quả tổng hợp. Điều này giúp thu được những thông tin hữu ích phục vụ cho việc ra quyết định trong kinh doanh.

Một trong các phương pháp thực hiện data aggregation trong MongoDB là aggregation pipeline.

Trong bài viết này sẽ giải thích:

  • Aggregation pipeline trong MongoDB là gì
  • Các stage khác nhau trong aggregation pipeline
  • Các expression có thể sử dụng trong aggregation pipeline

Mục lục

  • 4.1 Các giai đoạn của Aggregation Pipeline
  • 4.1.1 Stage $project
    • Bảng 4.1 Giá trị của <specification> trong $project
      • Ví dụ
      • Chỉ hiển thị một số field
  • 4.1.2 Stage $limit
      • Ví dụ
  • 4.1.3 Stage $group
    • Bảng 4.2 Tham số của $group
      • Các hàm accumulator phổ biến
    • Ví dụ $group
    • Ví dụ tiếp theo
    • Đổi thứ tự các stage
      • 📌 Lưu ý
  • 4.1.4 Stage $match
      • Nguyên lý hoạt động
  • 4.1.5 Stage $sort
    • Bảng 4.4: Các tham số của $sort
    • Ví dụ
  • 4.1.6 Stage $skip
    • Ví dụ
  • 4.1.7 Stage $addFields
    • Ví dụ
  • 4.1.8 Stage $out
    • Ví dụ
  • 4.1.9 Stage $merge
    • Các tham số của giai đoạn $merge
      • 1. into
      • 2. on
      • 3. whenMatched
      • 4. whenNotMatched
  • 4.1.10 $count stage
      • Cú pháp
      • Lưu ý
      • Ví dụ
      • Kết quả
  • 4.1.11 $sortByCount stage
      • Cú pháp
      • Ví dụ
      • Kết quả
  • 4.1.12 $sample stage
      • Cách hoạt động
      • Cú pháp
      • Ví dụ
      • Kết quả
  • 4.2 Aggregation Pipeline Operators
  • 4.2.1 Arithmetic Operators
    • Bảng 4.6 Arithmetic Operators
  • Ví dụ $add
      • Cú pháp
      • Ví dụ
      • Kết quả
  • 4.2 Aggregation Pipeline Operators
  • 4.2.1 Arithmetic Operators
    • Bảng 4.6: Arithmetic Operators
    • Ví dụ $add
      • Ví dụ
  • 4.2.2 Array Operators
    • Bảng 4.7: Array Operators
      • Các toán tử array bổ sung
    • Ví dụ $first và $last
      • Ví dụ
  • 4.2.3 Boolean Operators
    • Bảng 4.8: Boolean Operators
  • Ví dụ toán tử $and
    • Ví dụ thực tế
  • 4.2.4 Comparison Operators
    • Bảng 4.9: Comparison Operators
  • Ví dụ $gt và $lt
    • Ví dụ thực tế
  • 4.2.5 String Operators
    • Bảng 4.10: String Operators
  • Ví dụ $concat
    • Ví dụ thực tế

4.1 Các giai đoạn của Aggregation Pipeline

Trong MongoDB, pipeline là một chuỗi các stage xử lý dữ liệu.

Trong pipeline:

  • Stage đầu tiên lấy một số document từ database làm input
  • Thực hiện tính toán để tạo ra kết quả
  • Kết quả này được truyền sang stage tiếp theo
  • Quá trình tiếp tục cho đến stage cuối cùng của pipeline
  • Stage cuối cùng trả về kết quả tổng hợp (aggregated output)

Các stage của pipeline được đặt trong một mảng (array) của phương thức:

db.collection.aggregate()

Aggregation pipeline có thể gồm nhiều stage khác nhau. Trong session này sẽ thảo luận 9 stage quan trọng nhất của aggregation pipeline:

  • $project
  • $limit
  • $group
  • $match
  • $sort
  • $skip
  • $addFields
  • $merge
  • $out

4.1.1 Stage $project

Stage $project dùng để:

  • Lấy các document cần thiết
  • Thao tác với document bằng cách:
    • Thêm field mới
    • Xóa field hiện có
    • Thêm field được tính toán

Sau đó các document đã chỉnh sửa sẽ được chuyển sang stage tiếp theo.

Cú pháp:

{ $project: { <specification(s)> } }

Trong đó <specification(s)> có thể nhận các giá trị như trong Bảng 4.1.


Bảng 4.1 Giá trị của <specification> trong $project

ValueDescriptionExample
field: 0 hoặc falseField không được đưa vào kết quả{_id:0}
field: 1 hoặc trueField được đưa vào kết quả{certificate_number:1}
new field: expressionTạo field mới dựa trên expression{grade:"Grade field"}

Ví dụ

Giả sử người dùng muốn thực hiện aggregation trên dữ liệu trong collection inspections của database sample_training.

Để xem dữ liệu hiện có trong collection:

db.inspections.find()
Hình 4.1 hiển thị kết quả của truy vấn này.

Chỉ hiển thị một số field

Giả sử người dùng chỉ muốn xem các field:

  • certificate_number
  • business_name
  • address

Truy vấn:

db.inspections.aggregate([
 { $project :
   { certificate_number:1,
     business_name:1,
     address:1
   }
 }
])

Lưu ý:

Field _id được hiển thị mặc định, vì vậy nếu muốn loại bỏ nó cần đặt:

_id:0

Hình 4.2 hiển thị kết quả của truy vấn.

Kết quả trả về tất cả document nhưng chỉ chứa các field được chỉ định.


4.1.2 Stage $limit

Stage $limit được sử dụng để giới hạn số lượng document được chuyển sang stage tiếp theo.

Cú pháp:

{ $limit: <64-bit positive integer> }

Số document được chuyển sang stage tiếp theo được xác định bởi giá trị <64-bit positive integer>.


Ví dụ

Sử dụng $limit và $project trên collection inspections để trả về 2 document và chỉ hiển thị các field:

  • certificate_number
  • business_name
  • address

Truy vấn:

db.inspections.aggregate([
 { $limit:2 },
 { $project:{
    certificate_number:1,
    business_name:1,
    address:1
 }}
])
Hình 4.3 hiển thị kết quả của truy vấn.

4.1.3 Stage $group

Stage $group được sử dụng để nhóm các document dựa trên:

  • một field
  • một khóa
  • hoặc một nhóm field

Cú pháp:

{
 $group:{
   _id:<expression>,   // Group key
   <field1>:{<accumulator>:<expression>},
   ...
 }
}

Các tham số trong cú pháp này được mô tả trong Bảng 4.2.


Bảng 4.2 Tham số của $group

SpecificationDescription
_id:<expression>Xác định field dùng để nhóm dữ liệu
<field>Field dùng để tính toán
<accumulator>Hàm được áp dụng lên field

Các hàm accumulator phổ biến

FunctionDescription
$avgTính trung bình
$bottomLấy phần tử nhỏ nhất
$bottomNLấy N phần tử nhỏ nhất
$topLấy phần tử lớn nhất
$topNLấy N phần tử lớn nhất
$minGiá trị nhỏ nhất
$minNN giá trị nhỏ nhất
$maxGiá trị lớn nhất
$mergeObjectsGộp các document
$firstGiá trị của document đầu tiên
$lastGiá trị của document cuối cùng
$countĐếm số document
$sumTính tổng giá trị

Ví dụ $group

Giả sử người dùng muốn:

  • Nhóm document theo address.city
  • Đếm số document trong mỗi nhóm

Truy vấn:

db.inspections.aggregate([
 { $group:{
     _id:"$address.city",
     count:{ $count:{} }
 }}
])
Hình 4.4 hiển thị kết quả của truy vấn.

Ví dụ tiếp theo

Người dùng muốn:

  • Giới hạn 5000 document trước khi nhóm
  • Nhóm theo address.city
  • Đếm số document mỗi nhóm

Truy vấn:

db.inspections.aggregate([
  { $limit: 5000 },
  { $group: { _id: "$address.city", count: { $count: {} } } }
])

Hình 4.5: Kết quả $group kết hợp $limit

Đổi thứ tự các stage

Người dùng cũng có thể đổi thứ tự $group và $limit.

Ví dụ:

  • Nhóm document theo address.city
  • Đếm số document trong mỗi nhóm
  • Sau đó chỉ hiển thị 10 nhóm
db.inspections.aggregate([
  { $group: { _id: "$address.city", count: { $count: {} } } },
  { $limit: 10 }
])

Hình 4.6: Kết quả $group kết hợp $limit

📌 Lưu ý

Kết quả đầu ra sẽ thay đổi tùy theo thứ tự các stage trong pipeline.


4.1.4 Stage $match

Giai đoạn $match trong aggregation pipeline giúp lọc các document dựa trên một điều kiện, sau đó chuyển kết quả sang stage tiếp theo.

Cú pháp:

{$match: { <expression> } ... }

Nguyên lý hoạt động

$match nhận document làm đầu vào và lọc chúng theo biểu thức điều kiện.

Ví dụ:

Trong collection inspections, người dùng muốn:

  • Ẩn trường _id
  • Hiển thị các trường business_name và address.city
  • Chỉ lấy các document có address.city = "JERSEY CITY"
  • Giới hạn 10 document

Truy vấn:

db.inspections.aggregate([
 { $project: { _id:0, "address.city":1, business_name:1 } },
 { $match: { "address.city": "JERSEY CITY" } },
 { $limit:10 }
])

Hình 4.7: Kết quả $match với $limit và $project

4.1.5 Stage $sort

Như tên gọi, $sort dùng để sắp xếp các document theo thứ tự tăng hoặc giảm dựa trên một hoặc nhiều trường.

Danh sách đã sắp xếp sẽ được chuyển sang stage tiếp theo.

Nếu sắp xếp theo nhiều trường, MongoDB sẽ sắp xếp từ trái sang phải theo thứ tự các trường.

Cú pháp:

{$sort: { field1: <sort order>, field2: <sort order>, ... }}

Bảng 4.4: Các tham số của $sort

Tham sốMô tả
field1, field2Tên trường cần sắp xếp
sort order1 = tăng dần, -1 = giảm dần

Ví dụ

Trong collection inspections, người dùng muốn:

  • Sử dụng 5000 document
  • Ẩn trường _id
  • Hiển thị business_name và address.city
  • Sắp xếp theo:
    • address.city giảm dần
    • business_name tăng dần
  • Chỉ hiển thị 10 document

Truy vấn:

db.inspections.aggregate([
 { $project:{ _id:0,"address.city":1,business_name:1 } },
 { $limit:5000 },
 { $sort:{ "address.city":-1,"business_name":1 } },
 { $limit:10 }
])
Hình 4.8: Kết quả của $sort với $limit và $project

Trong kết quả:

  • Trường address.city được sắp xếp theo thứ tự giảm dần.
  • Vì vậy:
    • Các tên thành phố viết chữ thường sẽ xuất hiện trước theo thứ tự giảm dần.
    • Sau đó các tên thành phố viết chữ hoa cũng xuất hiện theo thứ tự giảm dần.
  • Hai bản ghi có cùng tên thành phố sẽ được sắp xếp tăng dần theo business_name như đã chỉ định.

4.1.6 Stage $skip

Giai đoạn $skip được dùng để bỏ qua một số document trước khi chuyển sang stage tiếp theo.

Cú pháp của $skip:

{$skip: <64-bit positive integer>}

Số lượng document được chuyển sang stage tiếp theo sẽ được kiểm soát bởi số lượng chỉ định trong <64-bit positive integer>.


Ví dụ

Giả sử người dùng muốn:

  • Sử dụng truy vấn giống truy vấn của $sort
  • Nhưng bỏ qua 10 document đầu tiên thay vì giới hạn kết quả là 10 document

Truy vấn:

db.inspections.aggregate([
 { $project:{ _id:0,"address.city":1,business_name:1 } },
 { $limit:5000 },
 { $sort:{ "address.city":-1,"business_name":1 } },
 { $skip:10 }
])

Hình 4.9: Kết quả $skip với $limit, $sort và $project

Trong kết quả:

  • 10 document đầu tiên (những document có address.city viết chữ thường) đã bị bỏ qua.

4.1.7 Stage $addFields

Đúng như tên gọi, giai đoạn $addFields được dùng để thêm một trường mới vào document.

Nó sẽ:

  1. Lấy các document từ stage trước
  2. Thêm trường mới được chỉ định
  3. Trả về document đã cập nhật cho stage tiếp theo

Cú pháp:

{$addFields: { <new field1>: <expression>, ... }}

Trong đó:

  • <new field1>: tên trường mới
  • <expression>: giá trị của trường

Người dùng có thể thêm nhiều trường trong một truy vấn.


Ví dụ

Trong collection inspections, người dùng muốn:

  • Thêm trường address.country
  • Giá trị = "USA"

Sau đó hiển thị các trường:

  • business_name
  • address.city
  • address.country

Cho 5 document.

Truy vấn:

db.inspections.aggregate([
 { $addFields:{ "address.country":"USA" } },
 { $limit:5 },
 { $project:{ _id:0,business_name:1,"address.city":1,"address.country":1 } }
])

Hình 4.10: Kết quả $addFields với $limit và $project

4.1.8 Stage $out

Giai đoạn $out dùng để ghi kết quả của pipeline vào một collection.

Nếu collection đã tồn tại:

  • $out sẽ ghi đè toàn bộ dữ liệu cũ bằng kết quả truy vấn.

Cú pháp:

{ $out: { db: "<output-db>", coll: "<output-collection>" } }

Trong đó:

  • db: tên database chứa collection kết quả
  • coll: tên collection kết quả

Ví dụ

Người dùng muốn:

  • Lấy 8 document từ collection inspections
  • Chỉ giữ các trường:
    • certificate_number
    • business_name
    • address
  • Lưu kết quả vào collection out_inspection1

Truy vấn:

db.inspections.aggregate([
 { $limit:8 },
 { $project:{ certificate_number:1,business_name:1,address:1 } },
 { $out:"out_inspection1" }
])

Sau đó để xem dữ liệu:

db.out_inspection1.find()

Hình 4.11: Các document trong collection out_inspection1

Collection out_inspection1 gồm 8 document, trong đó 2 document cuối có address.city = NEW YORK.

Bây giờ, giả sử người dùng muốn:

  • bỏ qua 10 document đầu tiên trong collection inspections
  • sau đó đưa vào collection out_inspection13 document có các trường:
    • certificate_number
    • business_name
    • address
  • với điều kiện address.city là NEW YORK

Để làm điều đó, người dùng có thể chạy truy vấn sau:

db.inspections.aggregate([
  { $skip: 10 },
  { $match: { "address.city": "NEW YORK" } },
  { $project: { certificate_number: 1, business_name: 1, address: 1 } },
  { $limit: 3 },
  { $out: "out_inspection1" }
])

Để xem các document trong collection out_inspection1, người dùng có thể chạy truy vấn:

db.out_inspection1.find()

Hình 4.12 hiển thị kết quả của truy vấn này.

Hình 4.12: Các document trong collection out_inspection1

Hình 4.12 cho thấy collection out_inspection1 hiện có 3 document thay vì 8 document ban đầu.

Điều này là do stage $out đã xóa các document trước đó và thay thế chúng bằng các document từ truy vấn gần nhất.


4.1.9 Stage $merge

Giai đoạn $merge tương tự như giai đoạn $out và được dùng để lưu kết quả đầu ra của pipeline vào một collection mới trong cùng database hoặc ở database khác.

Điểm khác biệt là $merge không xóa các document cũ.

Nó sử dụng một trường định danh (identifier) để xác định duy nhất document, và khi tìm thấy bản ghi trùng khớp thì nó thực hiện các hành động như:

  • thay thế document đang tồn tại
  • giữ nguyên document đang tồn tại
  • hoặc gộp (merge) các document

Nếu không tìm thấy bản ghi khớp, nó sẽ thực hiện các hành động như:

  • chèn document mới
  • loại bỏ document
  • hoặc báo lỗi

Đó là các hành động như chèn document hoặc loại bỏ document. Cú pháp của $merge như sau:

{
  $merge: {
    into: <collection> -or- { db: <db>, coll: <collection> },
    on: <identifier field> -or- [ <identifier field1>, ... ],
    let: <variables>,
    whenMatched: <replace|keepExisting|merge|fail|pipeline>,
    whenNotMatched: <insert|discard|fail>
  }
}

Danh sách phía dưới mô tả các tham số được sử dụng trong giai đoạn $merge.

Các tham số của giai đoạn $merge

1. into

Chỉ định collection mà các document sẽ được đưa vào trong cùng database nơi truy vấn đang được thực hiện.

Nếu không phải cùng database, tham số này sẽ chỉ định database và collection mà các document sẽ được ghi vào.

Nếu collection được chỉ định chưa tồn tại, MongoDB sẽ tạo một collection mới.

2. on

Chỉ định trường định danh duy nhất cho các document.

Nó được dùng để xác định xem một document trong kết quả truy vấn có khớp với một document trong collection đầu ra hay không.

3. whenMatched

Chỉ định hành động phải thực hiện nếu identifier của một document trong collection đầu ra khớp với identifier của document trong kết quả truy vấn.

Tham số này cho phép:

  • thay thế document đang tồn tại
  • giữ nguyên document đang tồn tại
  • hoặc gộp các document

Khi gộp document, các field còn thiếu trong collection đầu ra sẽ được thêm vào.

Nếu các field tồn tại ở cả hai document, giá trị từ kết quả truy vấn sẽ ghi đè lên giá trị trong collection đầu ra.

Nếu identifier trong kết quả truy vấn và collection đầu ra khớp nhau, thao tác merge cũng có thể bị lỗi tùy theo cấu hình.

4. whenNotMatched

Chỉ định hành động phải thực hiện nếu identifier của document trong collection đầu ra không khớp với identifier của document trong kết quả truy vấn.

Trong trường hợp này, document từ kết quả truy vấn có thể:

  • được chèn vào collection đầu ra
  • bị loại bỏ
  • hoặc thao tác merge có thể bị lỗi

Ví dụ, giả sử người dùng muốn đưa các document từ collection inspections vào collection out_inspection1, trong đó address.city là HAZLET.

Nếu tìm thấy bản ghi khớp, các document phải được thay thế trong collection out_inspection1.

Nếu không tìm thấy bản ghi khớp, document phải được chèn vào collection out_inspection1.

Để làm điều đó, người dùng có thể chạy truy vấn sau:

db.inspections.aggregate([
  { $skip: 10 },
  { $match: { "address.city": "HAZLET" } },
  { $project: { certificate_number: 1, business_name: 1, address: 1 } },
  {
    $merge: {
      into: {
        db: "sample_training",
        coll: "out_inspection1"
      },
      on: "_id",
      whenMatched: "replace",
      whenNotMatched: "insert"
    }
  }
])

Để xem các document trong collection out_inspection1, người dùng có thể chạy truy vấn:

db.out_inspection1.find()

Hình 4.13 hiển thị kết quả của truy vấn này.

Hình 4.13: Các document trong collection out_inspection1

Hình 4.13 cho thấy collection out_inspection1 hiện có 4 document thay vì 3 document ban đầu.

Lý do là document có address.city là HAZLET không tìm thấy bản ghi khớp, vì vậy document đó đã được chèn vào collection.

4.1.10 $count stage

Stage $count là một toán tử aggregation dùng để đếm số lượng document đi qua pipeline.

Nó thường được đặt ở cuối aggregation pipeline và trả về một document duy nhất chứa kết quả đếm.

Cú pháp

{ $count: "<outputField>" }

Trong đó:

  • <outputField> là tên field sẽ chứa kết quả đếm.

Lưu ý

$count không thể tùy chỉnh gì thêm ngoài việc đặt tên field output.

Nó phải được đặt sau các stage như:

  • $match
  • $project
  • hoặc các stage khác

để lọc hoặc định hình dữ liệu trước khi đếm.


Ví dụ

Nếu muốn đếm số user không hoạt động (inactive) và sống tại Los Angeles, ta có thể dùng $count.

db.users.aggregate([
  {
    $match: {
      city: "Los Angeles",
      isActive: false
    }
  },
  {
    $count: "inactive_users_in_LA"
  }
])

Kết quả

[
 { inactive_users_in_LA: 8 }
]

Truy vấn hoạt động theo trình tự:

1️⃣ $match lọc các document có:

city = "Los Angeles"
isActive = false

2️⃣ $count đếm số document thỏa điều kiện.


4.1.11 $sortByCount stage

Stage $sortByCount dùng để:

  • nhóm document theo một field
  • đếm số lượng document trong mỗi nhóm
  • tự động sắp xếp giảm dần theo count

Nó kết hợp chức năng của $group và $sort trong một bước.


Cú pháp

{ $sortByCount: "<field>" }

Trong đó:

<field> là tên field muốn group và đếm.


Ví dụ

Đếm số user trong mỗi thành phố và sắp xếp từ nhiều đến ít.

db.users.aggregate([
  { $sortByCount: "$city" }
])

Kết quả

{ _id: "New York", count: 15 }
{ _id: "Los Angeles", count: 14 }
{ _id: "Phoenix", count: 13 }
{ _id: "Philadelphia", count: 10 }
{ _id: "Dallas", count: 10 }
{ _id: "San Jose", count: 9 }
{ _id: "San Antonio", count: 9 }
{ _id: "Houston", count: 8 }
{ _id: "Chicago", count: 7 }
{ _id: "San Diego", count: 5 }

Ở đây:

  • _id = giá trị của field group (city)
  • count = số document thuộc nhóm đó.

4.1.12 $sample stage

Stage $sample dùng để lấy ngẫu nhiên một số document từ collection.

Nó đặc biệt hữu ích khi:

  • tạo mock dataset
  • hiển thị featured users / featured products
  • phân tích dữ liệu bằng random sampling

Cách hoạt động

MongoDB sẽ:

  • shuffle các document nội bộ
  • trả về số lượng document được yêu cầu
  • không phụ thuộc thứ tự dữ liệu ban đầu

Cú pháp

{ $sample: { size: <number> } }

Trong đó:

size là số document muốn lấy ngẫu nhiên.


Ví dụ

Lấy 5 user ngẫu nhiên để hiển thị.

db.users.aggregate([
 { $sample: { size: 5 } }
])

Kết quả

MongoDB trả về 5 document bất kỳ trong collection.

Ví dụ:

{
 name: "Bob Turner",
 age: 55,
 email: "[email protected]",
 city: "New York",
 isActive: false
}
{
 name: "Charlie Walker",
 age: 52,
 city: "Los Angeles",
 isActive: true
}
{
 name: "Fiona Turner",
 age: 51,
 city: "Houston"
}
{
 name: "Diana Turner",
 age: 57,
 city: "Philadelphia"
}
{
 name: "Diana Anderson",
 age: 19,
 city: "San Jose"
}

4.2 Aggregation Pipeline Operators

Các operator trong aggregation pipeline được dùng để thực hiện:

  • phép toán số học
  • phép toán logic
  • xử lý dữ liệu trong pipeline.

Các loại operator gồm:

  • Arithmetic operators
  • Array operators
  • Boolean operators
  • Comparison operators
  • String operators

4.2.1 Arithmetic Operators

Các toán tử số học thực hiện các phép toán trên dữ liệu và trả về một giá trị duy nhất.

Bảng 4.6 mô tả một số arithmetic operator trong MongoDB.


Bảng 4.6 Arithmetic Operators

OperatorChức năng
$addCộng nhiều số hoặc cộng số với date
$subtractTrừ hai số hoặc hai date
$multiplyNhân nhiều số
$divideChia hai số
$ceilLàm tròn lên
$floorLàm tròn xuống
$absGiá trị tuyệt đối
$powLũy thừa
$expe mũ x
$lnlog tự nhiên
$loglog theo base
$log10log cơ số 10
$modphép chia lấy dư
$roundlàm tròn
$sqrtcăn bậc hai
$trunccắt phần thập phân

Ví dụ $add

Cú pháp

$add: [ <expression1>, <expression2>, ... ]

Trong đó <expression> có thể là:

  • số
  • hoặc kết hợp số và date.

Ví dụ

Trong database sample_analytics, giả sử muốn:

  • tăng sales limit thêm 2000
  • lưu kết quả vào field newLimit
db.accounts.aggregate([
 {
   $project:{
     account_id:1,
     limit:1,
     newLimit:{
       $add:["$limit",2000]
     }
   }
 }
])

Kết quả

account_id: 371138
limit: 9000
newLimit: 11000
account_id: 674364
limit: 10000
newLimit: 12000

4.2 Aggregation Pipeline Operators

Các toán tử (operators) của aggregation pipeline được sử dụng trong nhiều stage của pipeline để thực hiện các phép tính số học hoặc logic.

Các loại toán tử aggregation pipeline gồm:

  • Arithmetic operators (toán tử số học)
  • Array operators (toán tử mảng)
  • Boolean operators (toán tử logic)
  • Comparison operators (toán tử so sánh)
  • String operators (toán tử chuỗi)

4.2.1 Arithmetic Operators

Các toán tử số học thực hiện các phép toán số học trên các toán hạng và trả về một giá trị duy nhất.

Bảng 4.6 mô tả một số toán tử số học trong MongoDB.


Bảng 4.6: Arithmetic Operators

OperatorMô tả
$addCộng hai hoặc nhiều số hoặc một số với một giá trị ngày. Nếu có giá trị date thì các giá trị khác được xem là milliseconds.
$subtractTrừ hai số hoặc hai ngày. Nếu trừ hai ngày sẽ trả về millisecond difference.
$multiplyNhân hai hoặc nhiều số.
$divideChia hai số.
$ceilTrả về số nguyên nhỏ nhất ≥ giá trị cho trước.
$floorTrả về số nguyên lớn nhất ≤ giá trị cho trước.
$absTrả về giá trị tuyệt đối của số.
$powTính lũy thừa của một số.
$expTính e^x (số Euler mũ x).
$lnLog tự nhiên.
$logLog với cơ số chỉ định.
$log10Log cơ số 10.
$modPhép chia lấy dư.
$roundLàm tròn số.
$sqrtCăn bậc hai.
$truncCắt phần thập phân của số.

Ví dụ $add

Cú pháp:

{$add:[<expression1>,<expression2>,...]}

Trong đó <expression> có thể là:

  • số
  • hoặc kết hợp giữa số và date.

Ví dụ

Trong database sample_analytics, người dùng muốn:

  • tăng limit bán hàng trong collection accounts thêm 2000
  • lưu kết quả vào field newLimit

Truy vấn:

db.accounts.aggregate([
 {
   $project:{
     account_id:1,
     limit:1,
     newLimit:{$add:["$limit",2000]}
   }
 }
])

Hình 4.17: Kết quả của $add

Kết quả hiển thị:

  • giá trị limit cũ
  • và newLimit = limit + 2000

4.2.2 Array Operators

Một array là tập hợp các giá trị thuộc cùng một biến.

Mỗi phần tử trong array có index bắt đầu từ 0.

MongoDB cung cấp nhiều toán tử làm việc với array.


Bảng 4.7: Array Operators

OperatorMô tả
$firstLấy phần tử đầu tiên của array
$firstNLấy N phần tử đầu tiên
$lastLấy phần tử cuối
$lastNLấy N phần tử cuối
$isArrayKiểm tra giá trị có phải array
$concatArraysNối nhiều array
$filterLọc phần tử của array theo điều kiện
$sortArraySắp xếp array
$maxNLấy N giá trị lớn nhất
$minNLấy N giá trị nhỏ nhất
$arrayElemAtLấy phần tử tại index xác định
$indexOfArrayTìm vị trí của phần tử trong array
$sizeĐếm số phần tử của array
$sliceLấy một phần của array
$arrayToObjectChuyển key-value array thành document
$objectToArrayChuyển document thành array
$inKiểm tra giá trị có trong array
$mapÁp dụng expression lên từng phần tử
$rangeTạo array theo dãy số

Các toán tử array bổ sung

OperatorDescription
$reduceÁp dụng expression cho từng phần tử rồi gộp kết quả
$reverseArrayĐảo thứ tự array
$zipGhép hai array lại theo index

Ví dụ $first và $last

Cú pháp:

$first:<expression>
$last:<expression>

<expression> phải trả về một array.


Ví dụ

Trong database sample_training, collection grades có:

scores = [exam, quiz, homework]

Người dùng muốn:

  • lấy điểm exam (phần tử đầu tiên của array).

Truy vấn:

db.grades.aggregate([
 {
   $addFields:{
     exam_score:{$first:"$scores"}
   }
 },
 {
   $project:{
     student_id:1,
     class_id:1,
     exam_score:1
   }
 }
])

Hình 4.18: Kết quả truy vấn với toán tử $first

Kết quả hiển thị:

  • student_id
  • class_id
  • exam_score

Bây giờ giả sử người dùng muốn lấy điểm bài tập (homework score), đây là phần tử cuối cùng trong mảng scores.

Để làm điều này, người dùng có thể chạy truy vấn với toán tử $last như sau:

db.grades.aggregate([
 { $addFields: { homework_score: { $last: "$scores" } } },
 { $project: { student_id:1, class_id:1, homework_score:1 } }
])

Hình 4.19: Kết quả truy vấn với toán tử $last

Kết quả hiển thị điểm homework của mỗi sinh viên, được lấy từ phần tử cuối của mảng scores.


4.2.3 Boolean Operators

Toán tử Boolean nhận các biểu thức (expressions) làm tham số và đánh giá chúng thành giá trị Boolean (true hoặc false).

Sau đó nó trả về một giá trị Boolean như mô tả trong Bảng 4.8.


Bảng 4.8: Boolean Operators

NameDescription
$andTrả về true nếu tất cả biểu thức đều đúng, ngược lại trả về false. Chấp nhận nhiều biểu thức.
$notTrả về true nếu biểu thức là false, và ngược lại. Chỉ chấp nhận một biểu thức.
$orTrả về true nếu ít nhất một biểu thức đúng. Chấp nhận nhiều biểu thức.

Ví dụ toán tử $and

Cú pháp:

{ $and: [ <expression1>, <expression2>, ... ] }

Trong cú pháp này:

<expression> có thể là bất kỳ biểu thức hợp lệ nào trả về giá trị Boolean.


Ví dụ thực tế

Trong database sample_training có collection trips, chứa:

  • tripduration
  • usertype

Giả sử người dùng muốn:

  • tạo field mới op_status
  • field này = true nếu:
tripduration = 379
và
usertype = "Subscriber"

Các document khác sẽ có op_status = false.

Truy vấn:

db.trips.aggregate([
 { $project:{ tripduration:1, usertype:1 }},
 { $addFields:{
      op_status:{
        $and:[
          {$eq:["$tripduration",379]},
          {$eq:["$usertype","Subscriber"]}
        ]
      }
 }},
 { $limit:4 }
])
Hình 4.20: Kết quả truy vấn với $and

Kết quả hiển thị field op_status cho mỗi document.

  • Nếu điều kiện đúng → true
  • Nếu sai → false

4.2.4 Comparison Operators

Như tên gọi của nó, toán tử so sánh dùng để so sánh hai biểu thức và trả về giá trị Boolean.

Bảng 4.9 liệt kê các toán tử so sánh.


Bảng 4.9: Comparison Operators

NameDescription
$cmpSo sánh hai biểu thức. Trả về: 0 nếu bằng nhau 1 nếu biểu thức thứ nhất lớn hơn -1 nếu nhỏ hơn
$eqTrả về true nếu hai biểu thức bằng nhau
$gtTrả về true nếu biểu thức thứ nhất lớn hơn
$gteTrả về true nếu biểu thức thứ nhất lớn hơn hoặc bằng
$ltTrả về true nếu biểu thức thứ nhất nhỏ hơn
$lteTrả về true nếu biểu thức thứ nhất nhỏ hơn hoặc bằng
$neTrả về true nếu hai biểu thức khác nhau

Ví dụ $gt và $lt

Cú pháp:

{ $gt/$lt: [ <expression1>, <expression2> ] }

Ví dụ thực tế

Trong database sample_analytics có collection accounts, chứa trường limit.

Người dùng muốn tìm các document có limit:

limit > 9000
và
limit < 12000

Truy vấn:

db.accounts.aggregate([
 {
   $project:{
     account_id:1,
     limit:1,
     limit_status:{
       $and:[
         {$gt:["$limit",9000]},
         {$lt:["$limit",12000]}
       ]
     },
     products:1
   }
 }
])

Hình 4.21: Kết quả truy vấn với $gt và $lt

Kết quả hiển thị:

  • account_id
  • limit
  • products
  • limit_status (true/false)

4.2.5 String Operators

Các toán tử chuỗi làm việc với dữ liệu kiểu string.

Một số toán tử được liệt kê trong Bảng 4.10.


Bảng 4.10: String Operators

NameDescription
$concatKết hợp nhiều chuỗi thành một chuỗi
$dateFromStringChuyển string thành date
$dateToStringChuyển date thành chuỗi
$indexOfBytesTìm vị trí substring theo UTF-8 byte index
$indexOfCPTìm vị trí substring theo UTF-8 code point index
$ltrimXóa khoảng trắng ở đầu chuỗi
$regexFindTìm substring đầu tiên khớp regex
$regexFindAllTìm tất cả substring khớp regex
$regexMatchKiểm tra chuỗi có khớp regex
$replaceOneThay thế lần xuất hiện đầu tiên
$replaceAllThay thế tất cả
$rtrimXóa khoảng trắng cuối chuỗi
$splitTách chuỗi thành mảng
$strLenBytesĐộ dài chuỗi theo UTF-8 bytes
$strLenCPĐộ dài chuỗi theo UTF-8 code points
$strcasecmpSo sánh chuỗi không phân biệt hoa thường
$toLowerChuyển chuỗi thành chữ thường
$toStringChuyển giá trị thành string
$trimXóa khoảng trắng đầu và cuối
$toUpperChuyển chuỗi thành chữ hoa

Ví dụ $concat

Cú pháp:

{ $concat: [ <expression1>, <expression2>, ... ] }

Ví dụ thực tế

Trong database sample_training có collection trips.

Collection này có:

  • start station name
  • end station name

Người dùng muốn:

  • ghép hai tên trạm
  • dùng dấu " - " làm dấu phân cách
  • lưu vào field source_destination.

Truy vấn:

db.trips.aggregate([
 {
   $project:{
     tripduration:1,
     source_destination:{
       $concat:[
         "$start station name",
         " - ",
         "$end station name"
       ]
     }
   }
 }
])

Hình 4.22: Kết quả truy vấn với $concat

Kết quả hiển thị:

Howard St & Centre St - E 17 St & Broadway
E 33 St & 2 Ave - South St & Whitehall St
Central Park S & 6 Ave - Central Park S & 6 Ave
...

Bài tập

Bối cảnh: quản lý sinh viên và điểm số.


Dataset mẫu

Tạo collection students:

db.students.insertMany([
{
 name: "An",
 age: 20,
 city: "Hanoi",
 scores: [7,8,9],
 major: "IT",
 active: true
},
{
 name: "Binh",
 age: 22,
 city: "Hanoi",
 scores: [6,7,8],
 major: "Business",
 active: false
},
{
 name: "Chi",
 age: 21,
 city: "Danang",
 scores: [9,9,8],
 major: "IT",
 active: true
},
{
 name: "Dung",
 age: 23,
 city: "Saigon",
 scores: [5,6,7],
 major: "Business",
 active: true
},
{
 name: "Ha",
 age: 20,
 city: "Saigon",
 scores: [8,7,9],
 major: "IT",
 active: false
},
{
 name: "Lan",
 age: 22,
 city: "Danang",
 scores: [6,8,7],
 major: "Marketing",
 active: true
}
])

Bài tập thực hành

Bài 1 — $project + $add

Tính tổng điểm của mỗi sinh viên

Yêu cầu output:

name
totalScore

Gợi ý:

$project
$add

Bài 2 — $match

Lấy sinh viên:

city = Hanoi
age > 20

Bài 3 — $group

Đếm số sinh viên theo city

Output:

city
count

Bài 4 — $group + $avg

Tính điểm trung bình của mỗi major

Output:

major
avgScore

Bài 5 — $sort + $limit

Lấy 3 sinh viên có tổng điểm cao nhất


Bài 6 — $skip

Bỏ qua 2 sinh viên đầu, lấy 3 sinh viên tiếp theo


Bài 7 — $addFields

Thêm field:

status = "pass" nếu totalScore >= 24
status = "fail" nếu < 24

Gợi ý:

$cond

Bài 8 — $sortByCount

Thống kê số sinh viên theo major


Bài 9 — $sample

Lấy 2 sinh viên random


Bài 10 — $count

Đếm số sinh viên active = true

Bài 11:

Viết 1 pipeline duy nhất:

  1. Lọc sinh viên active = true

  2. Tính totalScore

  3. Chỉ giữ các field

name
city
totalScore
  1. Sắp xếp theo totalScore giảm dần

  2. Lấy 3 sinh viên đầu


Các aggregrate sử dụng trong bài toán này:

Stage Dùng
$project ✔
$match ✔
$group ✔
$sort ✔
$limit ✔
$skip ✔
$addFields ✔
$count ✔
$sample ✔
$sortByCount ✔
$add ✔

Bài 2:

1. Tạo một database có tên Inventory và một collection có tên sales_invent.

Chèn các document sau vào collection sales_invent.

 

[ { customername: "Richard", gender: "M", purchased_product: "cereals", quantity: 6, price: 60 }, { customername: "Williams", gender: "M", purchased_product: "Vegetables", quantity: 10, price: 150 }, { customername: "Emma", gender: "F", purchased_product: "Fruits", quantity: 8, price: 200 }, { customername: "John", gender: "M", purchased_product: "Baby Food", quantity: 3, price: 300 }, { customername: "Smith", gender: "M", purchased_product: "Fruits", quantity: 5, price: 180 } ]

Sử dụng collection sales_invent, thực hiện các yêu cầu sau

3.

Loại bỏ trường _id và chỉ hiển thị 10 document đầu tiên của collection sales_invent, chỉ bao gồm các trường:

  • customername

  • purchased_product

  • price


4.

Sử dụng aggregation pipeline stages để:

  • Nhóm các document theo trường purchased_product

  • Tính tổng doanh thu (Total sale amount) cho mỗi sản phẩm

Chỉ trả về những sản phẩm có Total sale amount ≥ 500.


5.

Sử dụng aggregation pipeline stages để:

  • Chỉ hiển thị 3 document đầu tiên của collection sales_invent

  • Chỉ bao gồm các trường:

    • customername

    • purchased_product

  • Trong đó customername được sắp xếp tăng dần (ascending order).


6.

Thêm một trường mới có tên product_type với giá trị "edibles" vào tất cả các document trong collection sales_invent.


7.

Trong stage đầu tiên của aggregation pipeline:

  • Nhóm theo trường purchased_product

  • Cộng tất cả các giá trị của trường quantity

  • Lưu kết quả vào một trường mới có tên Total_quantity

Trong stage thứ hai:

  • Ghi (write) kết quả của stage đầu vào một collection mới tên Product_report

  • Collection này nằm trong cùng database Inventory.


8. Sử dụng toán tử biểu thức số học (arithmetic expression operator) để tính tổng giá trị (total price) theo công thức:

 

price * quantity

9. Chỉ hiển thị chi tiết sản phẩm trong trường hợp:

quantity > 5

10.

Sử dụng toán tử biểu thức chuỗi (string expression operator) để:

  • Nối (concatenate) hai trường:

customername + purchased_product

Lưu kết quả vào trường mới có tên customer_detail

Định dạng:

customername - purchased_product

Chỉ hiển thị kết quả cho khách hàng nam (male customers).

Bài viết liên quan:

Database Command trong MongoDB
Các toán tử trong MongoDB
Làm việc với cơ sở dữ liệu MongoDB
Giới thiệu mongoDB
Hướng dẫn cài đặt MongoDB trên môi trường windows, linux, macOS
Giới thiệu tổng quan và các khái niệm cơ bản về MongoDB

THÊM BÌNH LUẬN Cancel reply

Dịch vụ thiết kế Wesbite

NỘI DUNG MỚI CẬP NHẬT

Database Command trong MongoDB

Aggregation Pipeline – Các pipeline tổng hợp

Một số cải tiến trong ASP.NET Core, Razor Page, Model Binding, Gabbage collection

Các toán tử trong MongoDB

Làm việc với cơ sở dữ liệu MongoDB

Giới thiệu

hocvietcode.com là website chia sẻ và cập nhật tin tức công nghệ, chia sẻ kiến thức, kỹ năng. Chúng tôi rất cảm ơn và mong muốn nhận được nhiều phản hồi để có thể phục vụ quý bạn đọc tốt hơn !

Liên hệ quảng cáo: [email protected]

Kết nối với HỌC VIẾT CODE

© hocvietcode.com - Tech888 Co .Ltd since 2019

Đăng nhập

Trở thành một phần của cộng đồng của chúng tôi!
Registration complete. Please check your email.
Đăng nhập bằng google
Đăng kýBạn quên mật khẩu?

Create an account

Welcome! Register for an account
The user name or email address is not correct.
Registration confirmation will be emailed to you.
Log in Lost your password?

Reset password

Recover your password
Password reset email has been sent.
The email could not be sent. Possible reason: your host may have disabled the mail function.
A password will be e-mailed to you.
Log in Register
×