Với MongoDb 3.6 và mới hơn, bạn có thể tận dụng việc sử dụng $arrayToObject
toán tử và một $replaceRoot
để có được kết quả mong muốn. Bạn sẽ cần chạy đường dẫn tổng hợp sau:
db.users.aggregate([
{
"$group": {
"_id": { "$toLower": "$role" },
"count": { "$sum": 1 }
}
},
{
"$group": {
"_id": null,
"counts": {
"$push": {
"k": "$_id",
"v": "$count"
}
}
}
},
{
"$replaceRoot": {
"newRoot": { "$arrayToObject": "$counts" }
}
}
])
Đối với các phiên bản cũ hơn, $cond
toán tử trong $group
bước đường ống có thể được sử dụng hiệu quả để đánh giá số lượng dựa trên giá trị trường vai trò. Quy trình tổng hợp tổng thể của bạn có thể được xây dựng như sau để tạo ra kết quả ở định dạng mong muốn:
db.users.aggregate([
{
"$group": {
"_id": null,
"moderator_count": {
"$sum": {
"$cond": [ { "$eq": [ "$role", "moderator" ] }, 1, 0 ]
}
},
"superadmin_count": {
"$sum": {
"$cond": [ { "$eq": [ "$role", "superadmin" ] }, 1, 0 ]
}
},
"user_count": {
"$sum": {
"$cond": [ { "$eq": [ "$role", "user" ] }, 1, 0 ]
}
},
"admin_count": {
"$sum": {
"$cond": [ { "$eq": [ "$role", "admin" ] }, 1, 0 ]
}
}
}
},
{
"$project": {
"_id": 0,
"moderator": "$moderator_count",
"superadmin": "$superadmin_count",
"user": "$user_count",
"admin": "$admin_count"
}
}
])
Từ đường dẫn nhận xét, nếu bạn không biết trước các vai trò và muốn tạo mảng đường ống động, hãy chạy distinct
lệnh trên trường vai trò. Điều này sẽ cung cấp cho bạn một đối tượng chứa danh sách các vai trò riêng biệt:
var result = db.runCommand ( { distinct: "users", key: "role" } )
var roles = result.values;
printjson(roles); // this will print ["moderator", "superadmin", "user", "admin"]
Bây giờ được cung cấp danh sách ở trên, bạn có thể lắp ráp đường dẫn của mình bằng cách tạo một đối tượng sẽ có các thuộc tính được đặt bằng cách sử dụng reduce()
của JavaScript phương pháp. Sau đây chứng minh điều này:
var groupObj = { "_id": null },
projectObj = { "_id": 0 }
var groupPipeline = roles.reduce(function(obj, role) { // set the group pipeline object
obj[role + "_count"] = {
"$sum": {
"$cond": [ { "$eq": [ "$role", role ] }, 1, 0 ]
}
};
return obj;
}, groupObj );
var projectPipeline = roles.reduce(function(obj, role) { // set the project pipeline object
obj[role] = "$" + role + "_count";
return obj;
}, projectObj );
Sử dụng hai tài liệu này trong quy trình tổng hợp cuối cùng của bạn như:
db.users.aggregate([groupPipeline, projectPipeline]);
Kiểm tra bản trình diễn bên dưới.
var roles = ["moderator", "superadmin", "user", "admin"],
groupObj = { "_id": null },
projectObj = { "_id": 0 };
var groupPipeline = roles.reduce(function(obj, role) { // set the group pipeline object
obj[role + "_count"] = {
"$sum": {
"$cond": [ { "$eq": [ "$role", role ] }, 1, 0 ]
}
};
return obj;
}, groupObj );
var projectPipeline = roles.reduce(function(obj, role) { // set the project pipeline object
obj[role] = "$" + role + "_count";
return obj;
}, projectObj );
var pipeline = [groupPipeline, projectPipeline]
pre.innerHTML = JSON.stringify(pipeline, null, 4);
<pre id="pre"></pre>