sql >> Database >  >> NoSQL >> MongoDB

Is het mogelijk om meerdere kolommen te groeperen en op te tellen met het aggregatieraamwerk van MongoDB?

Sinds MongoDB 3.4 kan dit een beetje eenvoudiger worden bereikt met behulp van meerdere aggregatiepijplijnen met $facet .

overgenomen uit de docs :

Dus, voor jouw gebruiksgeval, zou dit worden bereikt door het volgende:

const aggregatorOpts = [
    { $match: { character: 'broquaint' } }, // Match the character
    {
        // Seperate into 2 or more pipes that will count class and
        // race seperatly
        $facet: {
            race: [
                // Group by race and get the count:
                // [
                //   {
                //     _id: 'Halfling',
                //     count: 3
                //   }
                //   {
                //     _id: 'Naga',
                //     count: 2
                //   }
                // ]

                // $sortByCount is the same as
                // { $group: { _id: <expression>, count: { $sum: 1 } } },
                // { $sort: { count: -1 } }

                { $sortByCount: '$race' },

                // Now we want to transform the array in to 1 document,
                // where the '_id' field is the key, and the 'count' is the value.
                // To achieve this we will use $arrayToObject. According the the
                // docs, we have to first rename the fields to 'k' for the key,
                // and 'v' for the value. We use $project for this:
                {
                    $project: {
                        _id: 0,
                        k: '$_id',
                        v: '$count',
                    },
                },
            ],
            // Same as above but for class instead
            class: [
                { $sortByCount: '$class' },
                {
                    $project: {
                        _id: 0,
                        k: '$_id',
                        v: '$count',
                    },
                },
            ],
        },
    },
    {
        // Now apply the $arrayToObject for both class and race.
        $addFields: {
            // Will override the existing class and race arrays
            // with their respective object representation instead.
            class: { $arrayToObject: '$class' },
            race: { $arrayToObject: '$race' },
        },
    },
];

db.races.aggregate(aggregatorOpts)

Wat het volgende oplevert:

[
  {
    "race": {
      "Halfling": 3,
      "Naga": 2
    },
    "class": {
      "Hunter": 3,
      "Rogue": 1,
      "Fighter": 1,
    }
  }
]

Als u tevreden bent met de uitvoeropmaak van @Asya, dan kunt u het $project . verwijderen en $addFields stadia, en verlaat gewoon de $sortByCount deel in elke subpijplijn.

Met deze nieuwe functies is de aggregatie een stuk eenvoudiger uit te breiden met extra tellingen. Voeg gewoon nog een aggregatiepijplijn toe in $facet .Het is zelfs een beetje makkelijker om subgroepen te tellen, maar dat zou een aparte vraag zijn.



  1. MongoDB $jaar

  2. Verbindingsprobleem met de nieuwste .Net MongoDb.Driver

  3. Hoe werkt de $inc-modifier met gelijktijdige verzoeken in mongodb?

  4. Hoe werkt het voorbeeld van het aantal berichten in Meteor-documenten?