根据您的应用程序需求,您可以使用聚合框架来计算分数并使用bulkWrite() https://docs.mongodb.org/manual/reference/method/db.collection.bulkWrite/#db.collection.bulkWrite更新您的收藏。考虑以下使用以下示例$project https://docs.mongodb.org/manual/reference/operator/aggregation/project/#pipe._S_project管道步骤作为使用算术运算符进行分数计算的余地。
由于计算逻辑C3
你的问题是从1
to 7
这正好等于7 - number of points (.)
,我能想到的唯一可行的方法是在进行聚合之前先存储一个额外的字段来保存该值。因此,您的第一步是创建该额外字段,您可以使用bulkWrite() https://docs.mongodb.org/manual/reference/method/db.collection.bulkWrite/#db.collection.bulkWrite如下:
第 1 步:修改架构以容纳额外的内容daysInWeek
field
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); }
理想情况下,上述操作还可以计算问题中的其他常量,从而创建Field8
因此。然而,我认为这样的计算应该在客户端完成,并让 MongoDB 在服务器上做它最擅长的事情。
步骤2:使用聚合进行添加Field8
field
创建了那个额外的字段daysInWeek
然后,您可以构建一个聚合管道,使用一组数据来投影新变量算术运算符 https://docs.mongodb.org/manual/reference/operator/aggregation-arithmetic/进行计算(再次建议在应用程序层进行此类计算)。最终的投影将是计算字段的乘积,然后您可以使用聚合结果游标进行迭代和添加Field8
到每个文档的集合:
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); }
对于 MongoDB>= 2.6
and <= 3.0
, 使用批量操作API https://docs.mongodb.org/manual/reference/method/Bulk/您需要使用光标迭代集合的地方forEach() https://docs.mongodb.org/manual/reference/method/cursor.forEach/方法,更新集合中的每个文档。
上述聚合管道中的一些算术运算符在 MongoDB 中不可用>= 2.6
and <= 3.0
所以你需要在forEach() https://docs.mongodb.org/manual/reference/method/cursor.forEach/迭代。
使用批量 API 通过批量捆绑每个更新并仅将集合中的每 500 个文档发送到服务器一次进行处理来减少服务器写入请求:
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(); }