Afhankelijk van uw toepassingsbehoeften, kunt u het aggregatieraamwerk gebruiken voor het berekenen van de score en de bulkWrite()
om uw collectie bij te werken. Overweeg het volgende voorbeeld dat de $project
pijplijnstap als speelruimte voor de scoreberekeningen met de rekenkundige operatoren.
Sinds logica voor het berekenen van C3
in uw vraag krijgt u een nummer van 1
tot 7
wat precies gelijk is aan 7 - aantal punten (.)
, de enige haalbare benadering die ik kan bedenken, is om een extra veld op te slaan dat deze waarde eerst bevat voordat de aggregatie wordt uitgevoerd. Dus je eerste stap zou zijn om dat extra veld aan te maken en je kunt dit doen met de bulkWrite()
als volgt:
Stap 1:Wijzig het schema om extra daysInWeek
op te vangen veld
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); }
In het ideale geval kan de bovenstaande bewerking ook de berekening van de andere constanten in uw vraag mogelijk maken en daarom het Veld8
maken als resultaat. Ik ben echter van mening dat dergelijke berekeningen op de client moeten worden gedaan en MongoDB moet laten doen wat het het beste kan op de server.
Stap 2:gebruik aggregatie om Field8
toe te voegen veld
Dat extra veld daysInWeek
. hebben gemaakt je kunt dan een aggregatiepijplijn construeren die de nieuwe variabelen projecteert met behulp van een cohort van rekenkundige operatoren
om de berekening uit te voeren (nogmaals, zou aanbevelen om dergelijke berekeningen op de applicatielaag uit te voeren). De uiteindelijke projectie is het product van de berekende velden die u vervolgens kunt gebruiken met de cursor voor het geaggregeerde resultaat om te herhalen en Field8
toe te voegen. naar de collectie bij elk document:
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); }
Voor MongoDB >=2.6
en <=3.0
, gebruik de Bulk Opeartions API
waar je de verzameling moet herhalen met de cursor forEach()
methode, werkt u elk document in de verzameling bij.
Sommige rekenkundige operatoren uit de bovenstaande aggregatiepijplijn zijn niet beschikbaar in MongoDB >=2.6
en <=3.0
dus je moet de berekeningen uitvoeren binnen de forEach()
iteratie.
Gebruik de bulk-API om schrijfverzoeken van de server te verminderen door elke update in bulk te bundelen en slechts één keer op de 500 documenten in de verzameling naar de server te verzenden voor verwerking:
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(); }