MongoDB
 sql >> Teknologi Basis Data >  >> NoSQL >> MongoDB

MongoDB menghitung skor dari bidang yang ada dan memasukkannya ke bidang baru dalam koleksi yang sama

Bergantung pada kebutuhan aplikasi Anda, Anda dapat menggunakan kerangka kerja agregasi untuk menghitung skor dan menggunakan bulkWrite() untuk memperbarui koleksi Anda. Perhatikan contoh berikut yang menggunakan $project langkah pipa sebagai kelonggaran untuk perhitungan skor dengan operator aritmatika.

Karena logika untuk menghitung C3 dalam pertanyaan Anda mendapatkan nomor dari 1 ke 7 yang sama persis dengan 7 - number of points (.) , satu-satunya pendekatan yang layak yang dapat saya pikirkan adalah menyimpan bidang tambahan yang menyimpan nilai ini terlebih dahulu sebelum melakukan agregasi. Jadi langkah pertama Anda adalah membuat bidang tambahan itu dan Anda dapat melakukannya menggunakan bulkWrite() sebagai berikut:

Langkah 1:Ubah skema untuk mengakomodasi daysInWeek tambahan bidang

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

Idealnya operasi di atas juga dapat mengakomodasi penghitungan konstanta lain dalam pertanyaan Anda dan karenanya membuat Field8 hasil dari. Namun saya percaya perhitungan seperti ini harus dilakukan pada klien dan biarkan MongoDB melakukan yang terbaik di server.

Langkah 2:Gunakan agregat untuk menambahkan Field8 bidang

Setelah membuat bidang ekstra itu daysInWeek Anda kemudian dapat membuat alur agregasi yang memproyeksikan variabel baru menggunakan kohort operator aritmatika untuk melakukan perhitungan (sekali lagi, akan merekomendasikan melakukan perhitungan seperti itu pada lapisan aplikasi). Proyeksi akhir akan menjadi produk dari bidang yang dihitung yang kemudian dapat Anda gunakan kursor hasil agregat untuk mengulangi dan menambahkan Field8 ke koleksi dengan setiap dokumen:

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

Untuk MongoDB >= 2.6 dan <= 3.0 , gunakan API Operasi Massal di mana Anda perlu mengulangi koleksi menggunakan kursor forEach() metode, perbarui setiap dokumen dalam koleksi.

Beberapa operator aritmatika dari pipa agregasi di atas tidak tersedia di MongoDB >= 2.6 dan <= 3.0 jadi Anda perlu melakukan perhitungan dalam forEach() iterasi.

Gunakan API massal untuk mengurangi permintaan penulisan server dengan menggabungkan setiap pembaruan secara massal dan mengirim ke server hanya sekali dalam setiap 500 dokumen dalam koleksi untuk diproses:

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. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Dapatkan BinData UUID dari Mongo sebagai string

  2. DeprecationWarning:Mendengarkan acara di kelas Db telah ditinggalkan dan akan dihapus di versi utama berikutnya

  3. MongoDB - Argumen ke $size harus berupa Array, tetapi bertipe:EOO / hilang

  4. Total ukuran penyimpanan MongoDB

  5. Hasil aneh dari mongoid menggunakan mongodb pemerasan Debian