Bạn sẽ cần sử dụng khung tổng hợp. Tổng hợp sẽ có kết quả giống như sau:
db.stack.aggregate([
{ $match: { "samples.key" : "test-key" } },
{ $unwind : "$samples" },
{ $match : { "samples.key" : "test-key" } },
{ $project : { "new_key" : "$samples.key", "new_value" : "$samples.value" } },
{ $group : { `_id` : "$new_key", answer : { $avg : "$new_value" } } }
])
Cách tốt nhất để nghĩ về khung tổng hợp giống như một dây chuyền lắp ráp. Bản thân truy vấn là một mảng tài liệu JSON, trong đó mỗi tài liệu con đại diện cho một bước khác nhau trong hợp ngữ.
Bước 1:$ match
Bước đầu tiên là một bộ lọc cơ bản, giống như mệnh đề WHERE trong SQL. Chúng tôi đặt bước này trước tiên để lọc ra tất cả các tài liệu không chứa phần tử mảng có chứa test-key
. Đặt điều này ở đầu đường ống cho phép tổng hợp sử dụng các chỉ mục.
Bước 2:$ thư giãn
Bước thứ hai, $unwind
, được sử dụng để tách từng phần tử trong mảng "mẫu" để chúng tôi có thể thực hiện các phép toán trên tất cả chúng. Nếu bạn chạy truy vấn chỉ với bước đó, bạn sẽ hiểu ý tôi. Câu chuyện ngắn:
{ name : "bob",
children : [ {"name" : mary}, { "name" : "sue" } ]
}
trở thành hai tài liệu:
{ name : "bob", children : [ { "name" : mary } ] }
{ name : "bob", children : [ { "name" : sue } ] }
Bước 3:$ match
Bước thứ ba, $match
, là bản sao chính xác của $match
đầu tiên sân khấu, nhưng có một mục đích khác. Vì nó theo sau $unwind
, giai đoạn này lọc ra các phần tử mảng trước đây, bây giờ là tài liệu, không phù hợp với tiêu chí bộ lọc. Trong trường hợp này, chúng tôi chỉ giữ lại các tài liệu có samples.key = "test-key"
Bước 4:$ project (Tùy chọn)
Bước thứ tư, $project
, cấu trúc lại tài liệu. Trong trường hợp này, tôi đã kéo các mục ra khỏi mảng để tôi có thể tham chiếu trực tiếp. Sử dụng ví dụ trên ..
{ name : "bob", children : [ { "name" : mary } ] }
trở thành
{ new_name : "bob", new_child_name : mary }
Lưu ý rằng bước này là hoàn toàn tùy chọn; các giai đoạn sau có thể được hoàn thành ngay cả khi không có $project
này sau một vài thay đổi nhỏ. Trong hầu hết các trường hợp, $project
hoàn toàn là mỹ phẩm; tổng hợp có nhiều cách tối ưu hóa ẩn như bao gồm hoặc loại trừ các trường trong $project
theo cách thủ công không cần thiết.
Bước 5:$ group
Cuối cùng, $group
là nơi điều kỳ diệu xảy ra. _id
coi trọng những gì bạn sẽ được "nhóm theo" trong thế giới SQL. Trường thứ hai nói là trung bình trên giá trị mà tôi đã xác định trong $project
bước chân. Bạn có thể dễ dàng thay thế $sum
để thực hiện tính tổng, nhưng thao tác đếm thường được thực hiện theo cách sau:my_count : { $sum : 1 }
.
Điều quan trọng nhất cần lưu ý ở đây là phần lớn công việc đang được thực hiện là định dạng dữ liệu đến một điểm mà việc thực hiện thao tác trở nên đơn giản.
Ghi chú cuối cùng
Cuối cùng, tôi muốn lưu ý rằng điều này sẽ không làm việc trên dữ liệu mẫu được cung cấp kể từ samples.value
được định nghĩa là văn bản, không thể được sử dụng trong các phép toán số học. Nếu bạn quan tâm, việc thay đổi loại trường được mô tả tại đây:MongoDB Cách thay đổi loại trường