sql >> データベース >  >> NoSQL >> MongoDB

MongoDBグループとidをキーとして合計

    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>


    1. Mongoose/MongoDBでのマルチフィールドインデックスの作成

    2. MongoDBドキュメントの再形成

    3. マングースの友達スキーマのモデリング?

    4. 集約中にMongoDBISODateからUNIXタイムスタンプを秒単位で取得する