sql >> Database teknologi >  >> NoSQL >> MongoDB

Beregn gennemsnittet af felter i indlejrede dokumenter/array

Aggregeringsrammen i MongoDB 3.4 og nyere tilbyder $reduce operatør, som effektivt beregner totalen uden behov for ekstra rørledninger. Overvej at bruge det som et udtryk for at returnere de samlede vurderinger og få antallet af vurderinger ved hjælp af $size . Sammen med $addFields , kan gennemsnittet således beregnes ved hjælp af den aritmetiske operator $divide som i formlen 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
                        ]
                    }
                ]
            }
        }
    }           
])

Eksempeloutput

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

Med ældre versioner skal du først anvende $unwind operatør på ratings matrixfelt først som dit indledende aggregeringspipelinetrin. Dette vil dekonstruere ratings matrixfelt fra inputdokumenterne for at udskrive et dokument for hvert element. Hvert outputdokument erstatter arrayet med en elementværdi.

Det andet pipelinetrin ville være $group operatør, som grupperer inputdokumenter efter _id og title nøgleidentifikatorudtryk og anvender den ønskede $avg akkumulatorudtryk til hver gruppe, der beregner gennemsnittet. Der er en anden akkumulatoroperator $push der bevarer det oprindelige bedømmelsesmatrixfelt ved at returnere en matrix af alle værdier, der er resultatet af at anvende et udtryk på hvert dokument i ovenstående gruppe.

Det sidste pipeline-trin er $project operatør, som derefter omformer hvert dokument i strømmen, f.eks. ved at tilføje det nye felt ratings_average .

Så hvis du for eksempel har et eksempeldokument i din samling (som ovenfra og så nedenfor):

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

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

For at beregne bedømmelsesmatrixgennemsnittet og projicere værdien i et andet felt ratings_average , kan du derefter anvende følgende aggregeringspipeline:

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

Resultat :

/* 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. Kunne ikke automatisk konfigurere en datakilde:'spring.datasource.url' er ikke angivet

  2. Redis pub/sub til chatserver i node.js

  3. hvordan man konfigurerer timeout for JedisConnectionFactory-basen på fjederstøvleramme

  4. node.js kan ikke finde modulet 'mongodb'