sql >> Database >  >> NoSQL >> MongoDB

MongoDB-groep en som met id als sleutel

Met MongoDb 3.6 en nieuwer kunt u gebruikmaken van $arrayToObject operator en een $replaceRoot pijplijn om het gewenste resultaat te krijgen. U zou de volgende geaggregeerde pijplijn moeten uitvoeren:

db.users.aggregate([
    { 
        "$group": {
            "_id": { "$toLower": "$role" },
            "count": { "$sum": 1 }
        }
    },
    { 
        "$group": {
            "_id": null,
            "counts": {
                "$push": {
                    "k": "$_id",
                    "v": "$count"
                }
            }
        }
    },
    { 
        "$replaceRoot": {
            "newRoot": { "$arrayToObject": "$counts" }
        } 
    }    
])

Voor oudere versies, de $cond operator in de $group pijplijnstap kan effectief worden gebruikt om de tellingen te evalueren op basis van de waarde van het rolveld. Uw algehele aggregatiepijplijn kan als volgt worden geconstrueerd om het resultaat in het gewenste formaat te produceren:

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"
        }
    }
])

Als u uit het opmerkingenspoor de rollen niet van tevoren kent en de pipeline-array dynamisch wilt maken, voert u de distinct uit commando op het rollenveld. Dit geeft je een object dat een lijst van de verschillende rollen bevat:

var result = db.runCommand ( { distinct: "users", key: "role" } )
var roles = result.values;
printjson(roles); // this will print ["moderator", "superadmin", "user",  "admin"]

Gezien de bovenstaande lijst, kunt u uw pijplijn samenstellen door een object te maken waarvan de eigenschappen zijn ingesteld met behulp van JavaScript's reduce() methode. Het volgende toont dit aan:

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 );

Gebruik deze twee documenten in uw uiteindelijke aggregatiepijplijn als:

db.users.aggregate([groupPipeline, projectPipeline]);

Bekijk de demo hieronder.

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. Prestaties van Redis vs Disk in caching-applicatie

  2. Objecteigenschappen opslaan in redis

  3. Wat is profiel? en Web en Worker

  4. MongoDB migreren naar DynamoDB, deel 2