Dependendo das necessidades do seu aplicativo, você pode usar a estrutura de agregação para calcular a pontuação e usar o
bulkWrite()
para atualizar sua coleção. Considere o exemplo a seguir que usa o $project
passo do pipeline como margem de manobra para os cálculos de pontuação com os operadores aritméticos. Desde lógica para calcular
C3
na sua pergunta está recebendo um número de 1
para 7
que equivale exatamente a 7 - number of points (.)
, a única abordagem viável que consigo pensar é armazenar um campo extra que retenha esse valor antes de fazer a agregação. Portanto, seu primeiro passo seria criar esse campo extra e você pode fazer isso usando o bulkWrite()
do seguinte modo:Etapa 1:modifique o esquema para acomodar mais
daysInWeek
campo 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); }
Idealmente, a operação acima também pode acomodar o cálculo das outras constantes em sua pergunta e, portanto, criar o
Field8
como resultado. No entanto, acredito que cálculos como esse devem ser feitos no cliente e deixar o MongoDB fazer o que faz de melhor no servidor. Etapa 2:use a agregação para adicionar
Field8
campo Tendo criado esse campo extra
daysInWeek
você pode então construir um pipeline de agregação que projeta as novas variáveis usando uma coorte de operadores aritméticos
para fazer o cálculo (novamente, recomendaria fazer tais cálculos na camada de aplicação). A projeção final será o produto dos campos calculados que você pode usar o cursor de resultado agregado para iterar e adicionar Field8
à coleção com cada documento: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); }
Para MongoDB
>= 2.6
e <= 3.0
, use a API de operações em massa
onde você precisa iterar a coleção usando o forEach()
método, atualize cada documento na coleção. Alguns dos operadores aritméticos do pipeline de agregação acima não estão disponíveis no MongoDB
>= 2.6
e <= 3.0
então você precisará fazer os cálculos dentro do forEach()
iteração. Use a API em massa para reduzir as solicitações de gravação do servidor agrupando cada atualização em massa e enviando ao servidor apenas uma vez a cada 500 documentos na coleção para processamento:
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(); }