Abhängig von Ihren Anwendungsanforderungen können Sie das Aggregations-Framework zur Berechnung der Punktzahl verwenden und die bulkWrite()
um Ihre Sammlung zu aktualisieren. Betrachten Sie das folgende Beispiel, das den Code
Seit Logik zur Berechnung von C3
In Ihrer Frage erhalten Sie eine Nummer von 1
bis 7
was genau 7 - Anzahl der Punkte (.)
entspricht , ist der einzig mögliche Ansatz, den ich mir vorstellen kann, ein zusätzliches Feld zu speichern, das diesen Wert enthält, bevor die Aggregation durchgeführt wird. Ihr erster Schritt wäre also, dieses zusätzliche Feld zu erstellen, und Sie können dies mit bulkWrite()
wie folgt:
Schritt 1:Ändern Sie das Schema, um zusätzliche daysInWeek
aufzunehmen Feld
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); }
Idealerweise kann die obige Operation auch die Berechnung der anderen Konstanten in Ihrer Frage berücksichtigen und somit das Field8
erstellen als Ergebnis. Ich glaube jedoch, dass Berechnungen wie diese auf dem Client durchgeführt werden sollten und MongoDB auf dem Server das tun lassen sollte, was es am besten kann.
Schritt 2:Verwenden Sie Aggregat, um Field8
hinzuzufügen Feld
Nachdem Sie dieses zusätzliche Feld daysInWeek
erstellt haben Sie können dann eine Aggregationspipeline erstellen, die die neuen Variablen mithilfe einer Kohorte von projiziert arithmetische Operatoren
um die Berechnung durchzuführen (wiederum würde ich empfehlen, solche Berechnungen auf der Anwendungsschicht durchzuführen). Die endgültige Projektion ist das Produkt der berechneten Felder, die Sie dann mit dem Aggregatergebnis-Cursor durchlaufen und Field8
hinzufügen können zur Sammlung mit jedem Dokument:
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); }
Für MongoDB >=2.6
und <=3.0
verwenden Sie die API für Massenoperationen
wo Sie die Sammlung mit dem des Cursors durchlaufen müssen forEach()
-Methode jedes Dokument in der Sammlung aktualisieren.
Einige der arithmetischen Operatoren aus der obigen Aggregationspipeline sind in MongoDB >=2.6
nicht verfügbar und <=3.0
Sie müssen also die Berechnungen im durchführen forEach()
Iteration.
Verwenden Sie die Bulk-API, um Server-Schreibanforderungen zu reduzieren, indem Sie jede Aktualisierung in großen Mengen bündeln und nur einmal alle 500 Dokumente in der Sammlung zur Verarbeitung an den Server senden:
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(); }