Khung tổng hợp trong MongoDB 3.4 và mới hơn cung cấp $reduce
nhà điều hành tính toán hiệu quả tổng số mà không cần thêm đường ống. Hãy xem xét sử dụng nó như một biểu thức để trả về tổng số xếp hạng và nhận số lượng xếp hạng bằng cách sử dụng $size
. Cùng với $addFields
, do đó, giá trị trung bình có thể được tính bằng toán tử số học $divide
như trong công thức average = total ratings/number of ratings
:
db.collection.aggregate([
{
"$addFields": {
"rating_average": {
"$divide": [
{ // expression returns total
"$reduce": {
"input": "$ratings",
"initialValue": 0,
"in": { "$add": ["$$value", "$$this.rating"] }
}
},
{ // expression returns ratings count
"$cond": [
{ "$ne": [ { "$size": "$ratings" }, 0 ] },
{ "$size": "$ratings" },
1
]
}
]
}
}
}
])
Đầu ra mẫu
{
"_id" : ObjectId("58ab48556da32ab5198623f4"),
"title" : "The Hobbit",
"ratings" : [
{
"title" : "best book ever",
"rating" : 5.0
},
{
"title" : "good book",
"rating" : 3.5
}
],
"rating_average" : 4.25
}
Với các phiên bản cũ hơn, trước tiên bạn cần áp dụng $unwind
toán tử trên ratings
trường mảng đầu tiên như là bước quy trình tổng hợp ban đầu của bạn. Điều này sẽ giải mã ratings
trường mảng từ các tài liệu đầu vào để xuất ra một tài liệu cho mỗi phần tử. Mỗi tài liệu đầu ra thay thế mảng bằng một giá trị phần tử.
Giai đoạn đường ống thứ hai sẽ là $group
toán tử nhóm các tài liệu đầu vào theo _id
và title
biểu thức mã định danh khóa và áp dụng $avg
mong muốn biểu thức tích lũy cho mỗi nhóm tính giá trị trung bình. Có một toán tử tích lũy khác $push
giữ nguyên trường mảng xếp hạng ban đầu bằng cách trả về một mảng gồm tất cả các giá trị là kết quả của việc áp dụng một biểu thức cho mỗi tài liệu trong nhóm trên.
Bước quy trình cuối cùng là $project
toán tử sau đó định hình lại từng tài liệu trong luồng, chẳng hạn như bằng cách thêm trường mới ratings_average
.
Vì vậy, nếu chẳng hạn, bạn có một tài liệu mẫu trong bộ sưu tập của mình (như từ bên trên và bên dưới):
db.collection.insert({
"title": "The Hobbit",
"ratings": [
{
"title": "best book ever",
"rating": 5
},
{
"title": "good book",
"rating": 3.5
}
]
})
Để tính toán mức trung bình của mảng xếp hạng và dự báo giá trị trong một trường khác ratings_average
, sau đó bạn có thể áp dụng quy trình tổng hợp sau:
db.collection.aggregate([
{
"$unwind": "$ratings"
},
{
"$group": {
"_id": {
"_id": "$_id",
"title": "$title"
},
"ratings":{
"$push": "$ratings"
},
"ratings_average": {
"$avg": "$ratings.rating"
}
}
},
{
"$project": {
"_id": 0,
"title": "$_id.title",
"ratings_average": 1,
"ratings": 1
}
}
])
Kết quả :
/* 1 */
{
"result" : [
{
"ratings" : [
{
"title" : "best book ever",
"rating" : 5
},
{
"title" : "good book",
"rating" : 3.5
}
],
"ratings_average" : 4.25,
"title" : "The Hobbit"
}
],
"ok" : 1
}