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

MongoDBは、既存のフィールドからスコアを計算し、それを同じコレクションの新しいフィールドに配置します

    アプリケーションのニーズに応じて、スコアを計算するための集計フレームワークを使用し、 bullkWrite() コレクションを更新します。 $ project 算術演算子を使用したスコア計算の余地としてのパイプラインステップ。

    C3を計算するためのロジック以降 あなたの質問では、 1から番号を取得しています 7へ これは正確に7に等しい-ポイント数(。) 、私が考えることができる唯一の実行可能なアプローチは、集計を行う前に、最初にこの値を保持する追加のフィールドを格納することです。したがって、最初のステップはその追加フィールドを作成することであり、 bullkWrite() 次のように:

    ステップ1:追加の daysInWeekに対応するようにスキーマを変更します フィールド

    var counter = 0, bulkUpdateOps = [];
    
    db.collection1.find({
        "Field5": { "$exists": true }
    }).forEach(function(doc) {
        // calculations for getting the number of points in Field5
        var points, daysInWeek;
        points = (doc.Field5.match(new RegExp(".", "g")) || []).length;
        daysInWeek = 7 - points;
        bulkUpdateOps.push({
            "updateOne": {
                "filter": { "_id": doc._id },
                "update": {
                    "$set": { "daysInWeek": daysInWeek }
                }
            }
        });
        counter++;
    
        if (counter % 500 == 0) {
            db.collection1.bulkWrite(bulkUpdateOps);
            bulkUpdateOps = [];
        }
    });
    
    if (counter % 500 != 0) { db.collection1.bulkWrite(bulkUpdateOps); }
    

    理想的には、上記の操作は、質問内の他の定数の計算に対応できるため、 Field8を作成することもできます。 結果として。ただし、このような計算はクライアントで実行し、MongoDBにサーバーで最適な処理を実行させる必要があると思います。

    ステップ2:集計を使用して Field8を追加します フィールド

    その余分なフィールドを作成したdaysInWeek 次に、のコホートを使用して、新しい変数を投影する集計パイプラインを構築できます。算術演算子 計算を実行します(ここでも、アプリケーション層でこのような計算を実行することをお勧めします)。最終的な投影は、計算されたフィールドの積になります。計算されたフィールドは、集計結果カーソルを使用して、 Field8を繰り返して追加できます。 各ドキュメントのコレクションへ:

    var pipeline = [
            {
                "$project": {
                    "C1": {
                        "$add": [ 
                            10, 
                            { "$multiply": [ "$Field3", 0.03 ] } 
                        ]
                    },
                    "C2": {
                        "$cond": [
                            { "$eq": [ "$Field2", 1 ] }, 
                            1, 
                            0.03 
                        ]
                    },
                    "C3": "$daysInWeek",
                    "C4": {
                        "$cond": [
                            { "$eq": [ "$Field2", 1 ]  },
                            { "$pow": [ "$Field4", -0.6 ] },
                            1
                        ]
                    }
                }
            },
            {
                "$project": {
                    "Field8": { "$multiply": [ "$C1", "$C2", "$C3", "$C4" ] }
                }
            }
        ],
        counter = 0,
        bulkUpdateOps = [];
    
    db.collection1.aggregate(pipeline).forEach(function(doc) {
        bulkUpdateOps.push({
            "updateOne": {
                "filter": { "_id": doc._id },
                "update": {
                    "$set": { "Field8": doc.Field8 }
                }
            }
        });
        counter++;
    
        if (counter % 500 == 0) {
            db.collection1.bulkWrite(bulkUpdateOps);
            bulkUpdateOps = [];
        }
    });
    
    if (counter % 500 != 0) { db.collection1.bulkWrite(bulkUpdateOps); }
    

    MongoDBの場合>=2.6 および<=3.0 Bulk OpeartionsAPI を使用します カーソルのを使用してコレクションを反復処理する必要がある場合forEach() メソッド、コレクション内の各ドキュメントを更新します。

    上記の集計パイプラインの算術演算子の一部は、MongoDB > =2.6では使用できません。 および<=3.0 したがって、 内で計算を行う必要があります。 forEach() 反復。

    バルクAPIを使用して、各更新を一括でバンドルし、処理のためにコレクション内の500ドキュメントごとに1回だけサーバーに送信することで、サーバー書き込み要求を減らします。

    var bulkUpdateOps = db.collection1.initializeUnorderedBulkOp(),
        cursor = db.collection1.find(), // cursor 
        counter = 0;
    
    cursor.forEach(function(doc) {
        // computations
        var c1, c2, c3, c4, Field8;
        c1 = 10 + (0.03*doc.Field3);
        c2 = (doc.Field2 == 1) ? 1: 0.03;
        c3 = 7 - (doc.Field5.match(new RegExp(".", "g")) || []).length;
        c4 = (doc.Field2 == 1) ? Math.pow(doc.Field, -0.6) : 1;
        Field8 = c1*c2*c3*c4;
    
        bulkUpdateOps.find({ "_id": doc._id }).updateOne({
            "$set": { "Field8": Field8 }
        });
    
        if (counter % 500 == 0) {
            bulkUpdateOps.execute();
            bulkUpdateOps = db.collection1.initializeUnorderedBulkOp();
        }
    })
    
    if (counter % 500 != 0) { bulkUpdateOps.execute(); }    
    


    1. ネストされた構造体をmgoで保存する

    2. フラッディングRAMなしでリアクティブな方法でmongodbコレクションからすべてのドキュメントをクエリするための最良の方法

    3. mongodb/mongoidを使用したランタイム変更モデル

    4. セカンダリインデックスでのRedisサポート