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