MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

MongoDB група и сума с идентификатор като ключ

С 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 pipeline step може да се използва ефективно за оценка на броя въз основа на стойността на полето за роля. Вашият цялостен тръбопровод за агрегиране може да бъде конструиран по следния начин, за да произведе резултата в желания формат:

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

Сега като имате списък по-горе, можете да сглобите своя тръбопровод, като създадете обект, който ще има своите свойства, зададени с помощта на reduce() на JavaScript метод. Следното демонстрира това:

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

Използвайте тези два документа във вашия окончателен конвейер за агрегиране като:

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. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Как MongoDB се справя с едновременните актуализации?

  2. 5 начина за избор на редове с максимална стойност за тяхната група в SQL

  3. Как да намерите произволен запис в Mongoose

  4. MongoDB има ли вграден REST интерфейс?

  5. Натиснете към два отделни масива в едно извикване за актуализиране в mongodb