sql >> Databáze >  >> NoSQL >> MongoDB

MongoDB počítá skóre z existujících polí a vkládá je do nového pole ve stejné kolekci

V závislosti na potřebách vaší aplikace můžete pro výpočet skóre použít agregační rámec a použít bulkWrite() aktualizovat svou sbírku. Zvažte následující příklad, který používá $project krok potrubí jako prostor pro výpočty skóre pomocí aritmetických operátorů.

Protože logika pro výpočet C3 ve vaší otázce získáváte číslo od 1 do 7 což se přesně rovná 7 - number of points (.) , jediný proveditelný přístup, který mě napadá, je před provedením agregace nejprve uložit další pole, které má tuto hodnotu. Takže vaším prvním krokem by bylo vytvořit toto další pole a můžete to udělat pomocí bulkWrite() takto:

Krok 1:Upravte schéma tak, aby obsahovalo další daysInWeek pole

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

V ideálním případě může výše uvedená operace také pojmout výpočet ostatních konstant ve vaší otázce, a proto vytvořit Field8 jako výsledek. Nicméně věřím, že výpočty, jako je tento, by se měly provádět na klientovi a nechat MongoDB dělat to, co umí nejlépe na serveru.

Krok 2:Pomocí agregace přidejte Field8 pole

Po vytvoření dodatečného pole daysInWeek pak můžete vytvořit agregační kanál, který promítá nové proměnné pomocí kohorty aritmetické operátory provést výpočet (opět bych doporučil provádět takové výpočty na aplikační vrstvě). Konečná projekce bude součinem vypočítaných polí, která pak můžete pomocí kurzoru agregovaného výsledku iterovat a přidat Field8 do sbírky s každým dokumentem:

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

Pro MongoDB >= 2.6 a <= 3.0 , použijte Bulk Operations API kde potřebujete iterovat kolekci pomocí kurzoru forEach() aktualizujte každý dokument ve sbírce.

Některé aritmetické operátory z výše uvedeného agregačního kanálu nejsou dostupné v MongoDB >= 2.6 a <= 3.0 takže budete muset provést výpočty v rámci forEach() iterace.

Pomocí hromadného rozhraní API můžete omezit požadavky na zápis na server tím, že každou aktualizaci hromadně spojíte a odešlete na server ke zpracování pouze jednou z každých 500 dokumentů v kolekci:

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. Příkaz MongoDB Agregation to Java code

  2. Nelze spustit docker mongo image v systému Windows

  3. MongoDB countDocuments()

  4. Nelze se připojit k Redis na 127.0.0.1:6379:Připojení odmítnuto s homebrew