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

マングースのサブドキュメントの合計

    Aggregate()を使用する 関数を使用すると、 $sumを使用する次のパイプラインを実行できます。 目的の結果を得るための演算子:

    const results = await Cart.aggregate([
        { "$addFields": {
            "totalPrice": {
                "$sum": "$products.subTotal"
            }
        } },
    ]);
    
    console.log(JSON.stringify(results, null, 4));
    

    対応する更新操作は次のとおりです。

    db.carts.updateMany(
       { },
       [
            { "$set": {
                "totalPrice": {
                    "$sum": "$products.subTotal"
                }
            } },
        ]
    )
    

    または、MongoDB 3.2以前のバージョンを使用している場合、 $ sum $groupステージでのみ利用可能です。実行できます

    const pipeline = [
        { "$unwind": "$products" },
        {
            "$group": {
                "_id": "$_id",
                "products": { "$push": "$products" },
                "userPurchased": { "$first": "$userPurchased" },
                "totalPrice": { "$sum": "$products.subTotal" }
            }
        }
    ]
    
    Cart.aggregate(pipeline)
        .exec(function(err, results){
            if (err) throw err;
            console.log(JSON.stringify(results, null, 4));
        })
    

    上記のパイプラインでは、最初のステップは $ unwind オペレーター

    { "$unwind": "$products" }
    

    これは、データが配列として格納されている場合に非常に便利です。アンワインド演算子がリストデータフィールドに適用されると、アンワインドが適用されるリストデータフィールドのすべての要素に対して新しいレコードが生成されます。基本的にデータをフラット化します。

    これは、次のパイプラインステージである $ group 平坦化されたドキュメントを_idでグループ化するステップ フィールド、したがって、非正規化されたドキュメントを元のスキーマに効果的に再グループ化します。

    $ group > パイプライン演算子は、SQLの GROUP BYに似ています 句。 SQLでは、 GROUP BYは使用できません。 集計関数のいずれかを使用しない限り。同様に、MongoDBの集計関数(アキュムレーターと呼ばれる)も使用する必要があります。 アキュムレータについて詳しくは、こちらをご覧ください

    この $ group 操作、 totalPriceを計算するロジック 元のフィールドを返すには、アキュムレータ> 。 totalPriceを取得します 個々のsubTotalを合計する $ sumを使用したグループごとの値 として:

    "totalPrice": { "$sum": "$products.subTotal }
    

    他の表現

    "userPurchased": { "$first": "$userPurchased" },
    

    userPurchasedを返します $ firstを使用した各グループの最初のドキュメントの値 。したがって、 の前に、元のドキュメントスキーマを効果的に再構築します。 $ unwind

    ここで注意すべきことの1つは、パイプラインを実行するときに、MongoDBがオペレーターを相互にパイプすることです。ここでの「パイプ」はLinuxの意味を取ります。演算子の出力は、次の演算子の入力になります。各演算子の結果は、ドキュメントの新しいコレクションです。したがって、Mongoは上記のパイプラインを次のように実行します。

    collection | $unwind | $group => result
    

    補足として、パイプラインの理解を支援したり、予期しない結果が発生した場合にデバッグしたりするには、最初のパイプライン演算子だけで集計を実行します。たとえば、mongoシェルで次のように集計を実行します:

    db.cart.aggregate([
        { "$unwind": "$products" }
    ])
    

    結果をチェックして、 productsかどうかを確認します 配列は適切に分解されます。それで期待どおりの結果が得られた場合は、次を追加します:

    db.cart.aggregate([
        { "$unwind": "$products" },
        {
            "$group": {
                "_id": "$_id",
                "products": { "$push": "$products" },
                "userPurchased": { "$first": "$userPurchased" },
                "totalPrice": { "$sum": "$products.subTotal" }
            }
        }
    ])
    

    パイプラインの最後のステップに到達するまで、ステップを繰り返します。

    フィールドを更新する場合は、 $ out 最後のステップとしてのパイプラインステージ。これにより、集計パイプラインの結果のドキュメントが同じコレクションに書き込まれるため、コレクションが技術的に更新されます。

    var pipeline = [
        { "$unwind": "$products" },
        {
            "$group": {
                "_id": "$_id",
                "products": { "$push": "$products" },
                "userPurchased": { "$first": "$userPurchased" },
                "totalPrice": { "$sum": "$products.subTotal" }
            }
        },
        { "$out": "cart" } // write the results to the same underlying mongo collection
    ]
    

    更新

    更新とクエリの両方を行うには、 find()を発行します。 集約コールバックを呼び出して、更新されたjsonを取得します。

    Cart.aggregate(pipeline)
        .exec(function(err, results){
            if (err) throw err;
            Cart.find().exec(function(err, docs){
                if (err) return handleError(err);
                console.log(JSON.stringify(docs, null, 4));
            })
        })
        
    

    Promisesを使用すると、代わりにこれを行うことができます

    Cart.aggregate(pipeline).exec().then(function(res)
        return Cart.find().exec();
    ).then(function(docs){  
        console.log(JSON.stringify(docs, null, 4));
    });
    


    1. MoongoseとGraphQLでエンティティを保存した後のデータがnull

    2. MongoDB:配列要素のプロパティの一意のインデックス

    3. 運用データベース管理

    4. MongoDBのインデックスデータ型のパフォーマンスへの影響?