sql >> Database >  >> NoSQL >> MongoDB

Bereken het gemiddelde van velden in ingesloten documenten/array

Het aggregatieraamwerk in MongoDB 3.4 en nieuwer biedt de $reduce operator die efficiënt het totaal berekent zonder dat er extra leidingen nodig zijn. Overweeg het te gebruiken als een uitdrukking om het totale aantal beoordelingen te retourneren en het aantal beoordelingen te krijgen met behulp van $size . Samen met $addFields , kan het gemiddelde dus worden berekend met behulp van de rekenkundige operator $divide zoals in de formule average = total ratings/number of ratings :

db.collection.aggregate([
    { 
        "$addFields": { 
            "rating_average": {
                "$divide": [
                    { // expression returns total
                        "$reduce": {
                            "input": "$ratings",
                            "initialValue": 0,
                            "in": { "$add": ["$$value", "$$this.rating"] }
                        }
                    },
                    { // expression returns ratings count
                        "$cond": [
                            { "$ne": [ { "$size": "$ratings" }, 0 ] },
                            { "$size": "$ratings" }, 
                            1
                        ]
                    }
                ]
            }
        }
    }           
])

Voorbeelduitvoer

{
    "_id" : ObjectId("58ab48556da32ab5198623f4"),
    "title" : "The Hobbit",
    "ratings" : [ 
        {
            "title" : "best book ever",
            "rating" : 5.0
        }, 
        {
            "title" : "good book",
            "rating" : 3.5
        }
    ],
    "rating_average" : 4.25
}

Bij oudere versies moet u eerst de $unwind . toepassen operator op de ratings array-veld eerst als uw eerste aggregatiepijplijnstap. Dit zal de ratings deconstrueren matrixveld uit de invoerdocumenten om een ​​document voor elk element uit te voeren. Elk uitvoerdocument vervangt de array door een elementwaarde.

De tweede pijplijnfase is de $group operator die invoerdocumenten groepeert op de _id en title sleutels identifier-expressie en past de gewenste $avg . toe accumulatoruitdrukking toe aan elke groep die het gemiddelde berekent. Er is een andere accumulator-operator $push dat het oorspronkelijke veld voor de classificatiearray behoudt door een array te retourneren van alle waarden die het resultaat zijn van het toepassen van een uitdrukking op elk document in de bovenstaande groep.

De laatste pijplijnstap is het $project operator die vervolgens elk document in de stream hervormt, bijvoorbeeld door het nieuwe veld ratings_average toe te voegen .

Dus als u bijvoorbeeld een voorbeelddocument in uw collectie heeft (zoals van boven en zo onder):

db.collection.insert({
    "title": "The Hobbit",

    "ratings": [
        {
            "title": "best book ever",
            "rating": 5
        },
        {
            "title": "good book",
            "rating": 3.5
        }
    ]
})

Om het gemiddelde van de beoordelingsreeks te berekenen en de waarde in een ander veld te projecteren ratings_average , kunt u vervolgens de volgende aggregatiepijplijn toepassen:

db.collection.aggregate([
    {
        "$unwind": "$ratings"
    },
    {
        "$group": {
            "_id": {
                "_id": "$_id",
                "title": "$title"
            },
            "ratings":{
                "$push": "$ratings"
            },
            "ratings_average": {
                "$avg": "$ratings.rating"
            }
        }
    },
    {
        "$project": {
            "_id": 0,
            "title": "$_id.title",
            "ratings_average": 1,
            "ratings": 1
        }
    }
])

Resultaat :

/* 1 */
{
    "result" : [ 
        {
            "ratings" : [ 
                {
                    "title" : "best book ever",
                    "rating" : 5
                }, 
                {
                    "title" : "good book",
                    "rating" : 3.5
                }
            ],
            "ratings_average" : 4.25,
            "title" : "The Hobbit"
        }
    ],
    "ok" : 1
}


  1. MongoDB pull-element van array twee niveaus diep

  2. Redigo ScanStruct-fout met time.Time

  3. MongoDB Gegevensmap /data/db niet gevonden

  4. ScaleGrid kondigt MongoDB-hostingservices aan in Canada