MongoDb 3.6以降では、 $arrayToObject
の使用を活用できます。 演算子と$replaceRoot
目的の結果を得るためのパイプライン。次の集約パイプラインを実行する必要があります:
db.users.aggregate([
{
"$group": {
"_id": { "$toLower": "$role" },
"count": { "$sum": 1 }
}
},
{
"$group": {
"_id": null,
"counts": {
"$push": {
"k": "$_id",
"v": "$count"
}
}
}
},
{
"$replaceRoot": {
"newRoot": { "$arrayToObject": "$counts" }
}
}
])
古いバージョンの場合、 $cond
$group
の演算子 パイプラインステップを効果的に使用して、ロールフィールドの値に基づいてカウントを評価できます。全体的な集計パイプラインは、次のように構築して、目的の形式で結果を生成できます。
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"
}
}
])
コメントトレイルから、事前に役割がわからず、パイプライン配列を動的に作成したい場合は、 distinct
を実行します。 ロールフィールドのコマンド。これにより、個別の役割のリストを含むオブジェクトが提供されます:
var result = db.runCommand ( { distinct: "users", key: "role" } )
var roles = result.values;
printjson(roles); // this will print ["moderator", "superadmin", "user", "admin"]
上記のリストがあれば、JavaScriptの reduce()
を使用してプロパティが設定されるオブジェクトを作成することで、パイプラインを組み立てることができます。 方法。以下はこれを示しています:
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 );
最終的な集計パイプラインで次の2つのドキュメントを使用します。
db.users.aggregate([groupPipeline, projectPipeline]);
以下のデモを確認してください。
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>