Tập hợp là một khung tổng hợp dữ liệu của MongoDB. Tập hợp được xây dựng dựa trên mô hình xử lý dữ liệu bên dưới định dạng đường ống. Aggregation pipeline bao gồm nhiều giai đoạn. Trong mỗi giai đoạn, chúng ta sử dụng một toán tử tổng hợp để biến đổi dữ liệu của các tài liệu đầu vào. Tài liệu đầu ra của giai đoạn phía trước sẽ là tài liệu đầu vào của giai đoạn ngay sau. Toán tử tổng hợp có thể được sử dụng nhiều lần trong đường ống, ngoại trừ $out
, $merge
và $geoNear
Điểm mạnh của aggregation framework là
- Xử lý nhanh và mạnh với ít băng thông
- Giải quyết các yêu cầu phức tạp
- It could work with large data
MongoDB cung cấp phương thức db.collection.aggregate[]
để chạy đường dẫn tổng hợp
cú pháp
1
2
db. Bộ sưu tập người dùng. tổng hợp[ [ { & . lt;stage 1> }, { <stage 2> }, .. . , { <stage N> } ], { <options> } ];
in which
- Giai đoạn được đặt trong một mảng theo thứ tự thực hiện trước sau
- Các tùy chọn là tùy chọn, không nhất thiết phải có
…
Để minh họa cho các nhà điều hành, mình sẽ sử dụng 2 bộ sưu tập là orders
và customers
Bộ sưu tập orders
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/* 1 */
{
"_id" . ObjectId["5dfed89743e6fed50628907c"],
"cust_id" . "A123",
"sản phẩm" . [
"quả táo",
"chanh"
],
"số tiền" . 500,
"trạng thái" . "hoàn thành"
}
/* 2 */
{
"_id" . ObjectId["5dfed8a643e6fed50628908a"],
"cust_id" . "B456",
"sản phẩm" . [
"chanh"
],
"số tiền" . 100,
"trạng thái" . "đang xử lý"
}
/* 3 */
{
"_id" . ObjectId["5dfed8b043e6fed50628908f"],
"cust_id" . "B456",
"sản phẩm" . [
"quả táo",
"cam"
],
"số tiền" . 300,
"trạng thái" . "hoàn thành"
}
/* 4 */
{
"_id" . ObjectId["5dfed8b943e6fed506289094"],
"cust_id" . "C789",
"sản phẩm" . [
"quả táo",
"chanh",
"cam"
],
"số tiền" . 800,
"trạng thái" . "hoàn thành"
}
/* 5 */
{
"_id" . ObjectId["5dfed8c343e6fed506289097"],
"cust_id" . "A123",
"sản phẩm" . [
"quả táo"
],
"số tiền" . 250,
"trạng thái" . "hoàn thành"
}
Bộ sưu tập customers
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* 1 */
{
"_id". "A123",
"tên". "Alice"
}
/* 2 */
{
"_id". "B456",
"tên". "Bob"
}
/* 3 */
{
"_id". "C789",
"tên". "Carol"
}
2. ________số 8
$match
được sử dụng để lọc các tài liệu theo một điều kiện nào đó. $match
tương tự như $merge
1 và $merge
2 trong SQL
cú pháp
1
2
{ $khớp. { <truy vấn> } }
Cú pháp truy vấn của $match
y cú pháp của truy vấn thao tác đọc [tương tự như $merge
4]
Ví dụ
Lọc đơn hàng của khách hàng có ID là A123
1
2
3
4
5
6
7
8
db. đơn đặt hàng. tổng hợp[[
{
$trận đấu. {
cust_id. "A123"
}
}
]]
=> Kết quả
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* 1 */
{
"_id" . ObjectId["5dfed89743e6fed50628907c"],
"cust_id" . "A123",
"sản phẩm" . [
"quả táo",
"chanh"
],
"số tiền" . 500,
"trạng thái" . "hoàn thành"
}
/* 2 */
{
"_id" . ObjectId["5dfed8c343e6fed506289097"],
"cust_id" . "A123",
"sản phẩm" . [
"quả táo"
],
"số tiền" . 250,
"trạng thái" . "hoàn thành"
}
3. $merge
5
$merge
5 được sử dụng để chỉ định các trường sẽ xuất hiện trong tài liệu đầu ra. Đó có thể là các trường đã tồn tại trong tài liệu đầu vào, hoặc cũng có thể là các trường được tính toán mới. $merge
5 tương tự như $merge
8 trong SQL
cú pháp
1
2
{ $dự án. { <đặc điểm kỹ thuật[s]> } }
in which
$merge
9 may have a following format
$geoNear
0. trường$geoNear
1 sẽ không xuất hiện trong tài liệu đầu ra [default$geoNear
1 luôn xuất hiện trong tài liệu đầu ra]$geoNear
3. trường X sẽ xuất hiện trong tài liệu đầu ra$geoNear
4. trường X sẽ được tính toán dựa trên bất kỳ biểu thức nào
Ví dụ
1
2
3
4
5
6
7
8
9
10
db. đơn đặt hàng. tổng hợp[[
{
$dự án. {
_id. 0,
cust_id. 1,
new_amount. { $thêm. ["$amount", 100] }
}
}
]]
=> Kết quả
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/* 1 */
{
"cust_id" . "A123",
"số_lượng_mới" . 600. 0
}
/* 2 */
{
"cust_id" . "B456",
"số_lượng_mới" . 200. 0
}
/* 3 */
{
"cust_id" . "B456",
"số_lượng_mới" . 400. 0
}
/* 4 */
{
"cust_id" . "C789",
"số_lượng_mới" . 900. 0
}
/* 5 */
{
"cust_id" . "A123",
"số_lượng_mới" . 350. 0
}
4. $geoNear
5
$geoNear
5 mới xuất hiện trong MongoDB phiên bản 3. 4. $geoNear
5 trả về bổ sung trong đầu ra một trường X chứa tổng số tài liệu đầu vào
cú pháp
1
2
{ $số lượng. <chuỗi> }
in which
$geoNear
8 là tên của trường X, phải trống khác, không được bắt đầu bằng ký tự $geoNear
9 và không được bao gồm ký tự db.collection.aggregate[]
0
Ví dụ
1
2
3
4
5
6
db. đơn đặt hàng. tổng hợp[[
{
$số lượng. "tổng"
}
]]
=> Kết quả
1
2
3
4
5
/* 1 */
{
"tổng" . 5
}
5. db.collection.aggregate[]
1 và db.collection.aggregate[]
2
db.collection.aggregate[]
1 was used to limit the quality output document. db.collection.aggregate[]
2 was used to only the value of document will drop in output [tính từ tài liệu đầu tiên]. db.collection.aggregate[]
1 và db.collection.aggregate[]
2 tương tự như db.collection.aggregate[]
7 và db.collection.aggregate[]
8 trong SQL
cú pháp
1
2
{ $giới hạn. <dương số nguyên> }
1
2
{ $bỏ qua. <dương số nguyên> }
Ví dụ
Nhận lệnh thứ 3 và thứ 4
1
2
3
4
5
6
7
8
9
db. đơn đặt hàng. tổng hợp[[
{
$bỏ qua. 2
},
{
$giới hạn. 2
}
]]
=> Kết quả
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/* 1 */
{
"_id" . ObjectId["5dfed8b043e6fed50628908f"],
"cust_id" . "B456",
"sản phẩm" . [
"quả táo",
"cam"
],
"số tiền" . 300,
"trạng thái" . "hoàn thành"
}
/* 2 */
{
"_id" . ObjectId["5dfed8b943e6fed506289094"],
"cust_id" . "C789",
"sản phẩm" . [
"quả táo",
"chanh",
"cam"
],
"số tiền" . 800,
"trạng thái" . "hoàn thành"
}
6. db.collection.aggregate[]
9
db.collection.aggregate[]
9 được dùng để sắp xếp các tài liệu trong đầu ra theo một tiêu chí nào đó. db.collection.aggregate[]
9 tương tự như orders
2 trong SQL
cú pháp
1
2
{ $sắp xếp. { <trường1 . >: <sắp xếp thứ tự . >, <field2>: <sắp xếp thứ tự . > .. . } }
Trong đó, orders
3 có thể có các giá trị sau
orders
4. sắp xếp theo thứ tự tăng dầnorders
5. sắp xếp theo thứ tự giảm dần
Ví dụ
Sắp xếp các thứ tự theo thứ tự giảm dần của số tiền
1
2
3
4
5
6
db. đơn đặt hàng. tổng hợp[[
{
$sắp xếp. { số tiền. -1 }
}
]]
=> Kết quả
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/* 1 */
{
"_id" . ObjectId["5dfed8b943e6fed506289094"],
"cust_id" . "C789",
"sản phẩm" . [
"quả táo",
"chanh",
"cam"
],
"số tiền" . 800,
"trạng thái" . "hoàn thành"
}
/* 2 */
{
"_id" . ObjectId["5dfed89743e6fed50628907c"],
"cust_id" . "A123",
"sản phẩm" . [
"quả táo",
"chanh"
],
"số tiền" . 500,
"trạng thái" . "hoàn thành"
}
/* 3 */
{
"_id" . ObjectId["5dfed8b043e6fed50628908f"],
"cust_id" . "B456",
"sản phẩm" . [
"quả táo",
"cam"
],
"số tiền" . 300,
"trạng thái" . "hoàn thành"
}
/* 4 */
{
"_id" . ObjectId["5dfed8c343e6fed506289097"],
"cust_id" . "A123",
"sản phẩm" . [
"quả táo"
],
"số tiền" . 250,
"trạng thái" . "hoàn thành"
}
/* 5 */
{
"_id" . ObjectId["5dfed8a643e6fed50628908a"],
"cust_id" . "B456",
"sản phẩm" . [
"chanh"
],
"số tiền" . 100,
"trạng thái" . "đang xử lý"
}
7. orders
6
orders
6 được dùng để gom nhóm các tài liệu đầu vào theo biểu thức $geoNear
1. Mỗi nhóm tương ứng với một tài liệu đầu ra. Trong orders
6, chúng ta có thể sử dụng các biểu thức tích lũy như customers
0, customers
1, customers
2, customers
3, …
orders
6 tương tự như customers
5 trong SQL
cú pháp
1
2
3
4
5
6
7
8
9
{
$nhóm.
{
_id. <biểu thức>, // Group By Expression
<trường1>: { <accumulator1 . > : <biểu thức1> },
. . .
}
}
Nếu $geoNear
1 được đặt bằng customers
7, MongoDB sẽ truy vấn tất cả các tài liệu đầu vào
Ví dụ
Gom group order by customers
8, đồng thời tính tổng số tiền của từng customers
8
1
2
3
4
5
6
7
8
9
db. đơn đặt hàng. tổng hợp[[
{
$nhóm. {
_id. "$cust_id",
tổng. { $tổng. "$amount" }
}
}
]]
=> Kết quả
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* 1 */
{
"_id" . "B456",
"tổng" . 400
}
/* 2 */
{
"_id" . "C789",
"tổng" . 800
}
/* 3 */
{
"_id" . "A123",
"tổng" . 750
}
8. orders
0
orders
0 được sử dụng để phân tách giá trị của một trường mảng trong tài liệu đầu vào. Nếu như trường mảng của một tài liệu đầu vào có N phần tử thì trong đầu ra sẽ có N tài liệu
cú pháp
1
2
{ $thư giãn. <trường đường dẫn> }
Ví dụ
Mình sẽ thử áp dụng orders
0 với trường mảng orders
3 để xem kết quả nó sẽ như thế nào
1
2
3
4
5
6
db. đơn đặt hàng. tổng hợp[[
{
$thư giãn. "$products"
}
]]
=> Kết quả
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/* 1 */
{
"_id" . ObjectId["5dfed89743e6fed50628907c"],
"cust_id" . "A123",
"sản phẩm" . "quả táo",
"số tiền" . 500,
"trạng thái" . "hoàn thành"
}
/* 2 */
{
"_id" . ObjectId["5dfed89743e6fed50628907c"],
"cust_id" . "A123",
"sản phẩm" . "chanh",
"số tiền" . 500,
"trạng thái" . "hoàn thành"
}
/* 3 */
{
"_id" . ObjectId["5dfed8a643e6fed50628908a"],
"cust_id" . "B456",
"sản phẩm" . "chanh",
"số tiền" . 100,
"trạng thái" . "đang xử lý"
}
/* 4 */
{
"_id" . ObjectId["5dfed8b043e6fed50628908f"],
"cust_id" . "B456",
"sản phẩm" . "quả táo",
"số tiền" . 300,
"trạng thái" . "hoàn thành"
}
/* 5 */
{
"_id" . ObjectId["5dfed8b043e6fed50628908f"],
"cust_id" . "B456",
"sản phẩm" . "cam",
"số tiền" . 300,
"trạng thái" . "hoàn thành"
}
/* 6 */
{
"_id" . ObjectId["5dfed8b943e6fed506289094"],
"cust_id" . "C789",
"sản phẩm" . "quả táo",
"số tiền" . 800,
"trạng thái" . "hoàn thành"
}
/* 7 */
{
"_id" . ObjectId["5dfed8b943e6fed506289094"],
"cust_id" . "C789",
"sản phẩm" . "chanh",
"số tiền" . 800,
"trạng thái" . "hoàn thành"
}
/* số 8 */
{
"_id" . ObjectId["5dfed8b943e6fed506289094"],
"cust_id" . "C789",
"sản phẩm" . "cam",
"số tiền" . 800,
"trạng thái" . "hoàn thành"
}
/*9 */
{
"_id" . ObjectId["5dfed8c343e6fed506289097"],
"cust_id" . "A123",
"sản phẩm" . "quả táo",
"số tiền" . 250,
"trạng thái" . "hoàn thành"
}
9. orders
4
orders
4 cho phép chúng ta thực hiện một phép nối ngoài trái giữa hai bộ sưu tập trong cùng một cơ sở dữ liệu. Với mỗi tài liệu đầu vào, orders
4 sẽ bổ sung một trường mảng chứa các phần tử khớp với bộ sưu tập được tham gia
cú pháp
1
2
3
4
5
6
7
8
9
10
{
$tra cứu.
{
từ. <bộ sưu tập đến join>,
localField. <trường từthe input documents>,
foreignField. <trường từthe documents of the "from" collection>,
như. <đầu ra mảng field>
}
}
in which
- Bộ sưu tập
orders
7 could not be shard orders
8 có thể có bất kỳ tên nào, nhưng nếu một trường nào đó trong tài liệu đã có tên như vậy thì giá trị của trường đó sẽ bị ghi đè
orders
4 tương đương với SQL sau đoạn
1
2
3
4
5
6