sql >> データベース >  >> NoSQL >> MongoDB

埋め込まれたドキュメント/配列のフィールドの平均を計算します

    MongoDB 3.4以降の集約フレームワークは、 $reduceを提供します 追加のパイプラインを必要とせずに合計を効率的に計算する演算子。これを式として使用して、合計評価を返し、 $sizeを使用して評価数を取得することを検討してください。 $addFieldsと一緒に したがって、平均は算術演算子 $divideを使用して計算できます。 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
                            ]
                        }
                    ]
                }
            }
        }           
    ])
    

    サンプル出力

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

    古いバージョンでは、最初に $unwindを適用する必要があります ratingsの演算子 最初の集計パイプラインステップとして、最初に配列フィールド。これにより、ratingsが分解されます 各要素のドキュメントを出力するための入力ドキュメントの配列フィールド。各出力ドキュメントは、配列を要素値に置き換えます。

    2番目のパイプラインステージは$groupになります 入力ドキュメントを_idでグループ化する演算子 およびtitle キー識別子式と目的の$avgを適用します 平均を計算する各グループへのアキュムレータ式。別のアキュムレータ演算子$pushがあります 上記のグループの各ドキュメントに式を適用した結果のすべての値の配列を返すことにより、元の評価配列フィールドを保持します。

    パイプラインの最後のステップは、 $projectです。 次に、新しいフィールドratings_averageを追加するなどして、ストリーム内の各ドキュメントの形状を変更する演算子 。

    したがって、たとえば、コレクションにサンプルドキュメントがある場合(上などから):

    db.collection.insert({
        "title": "The Hobbit",
    
        "ratings": [
            {
                "title": "best book ever",
                "rating": 5
            },
            {
                "title": "good book",
                "rating": 3.5
            }
        ]
    })
    

    評価配列の平均を計算し、値を別のフィールドに投影するにはratings_average 、次の集計パイプラインを適用できます:

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

    結果

    /* 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. MongoDB2.6アグリゲーションフレームワークの改善

    2. phpでアップサートした後にmongodb_idオブジェクトを取得します

    3. BookSleeveでredisのコンテンツ値を検索する方法

    4. MongoDBで個別の値を返す3つの方法