执行此操作的最有效方法是在撰写本文时即将发布的 MongoDB 中,使用 $split 运算符将我们的字符串拆分为 shown here,然后使用 @987654322 将数组中的最后一个元素分配给一个变量@ 变量运算符和 $arrayElemAt 运算符。
接下来,我们使用$switch 运算符对该变量执行逻辑条件处理或case 语句。
这里的条件是$gt,如果值包含"test",则返回true,在这种情况下,在in表达式中,我们拆分该字符串并简单地返回$concatenated值新计算的数组中的第一个元素和-。如果条件为 false,我们只返回变量。
当然,在我们的 case 语句中,我们使用 $indexOfCP,如果没有出现 "test",则返回 -1。
let cursor = db.collection.aggregate(
[
{ "$project": {
"data": 1,
"version": {
"$let": {
"vars": {
"v": {
"$arrayElemAt": [
{ "$split": [ "$version", "." ] },
-1
]
}
},
"in": {
"$switch": {
"branches": [
{
"case": {
"$gt": [
{ "$indexOfCP": [ "$$v", "test" ] },
-1
]
},
"then": {
"$concat": [
"-",
"",
{ "$arrayElemAt": [
{ "$split": [ "$$v", "-" ] },
0
]}
]
}
}
],
"default": "$$v"
}
}
}
}
}}
]
)
聚合查询产生如下内容:
{ "_id" : ObjectId("57a98773cbbd42a2156260d8"), "data" : 11, "version" : "32" }
{ "_id" : ObjectId("57a98773cbbd42a2156260d9"), "data" : 55, "version" : "-42" }
如您所见,“版本”字段数据是字符串。如果该字段的数据类型无关紧要,您可以简单地使用 $out 聚合管道阶段运算符将结果写入新集合或替换您的集合。
{ "out": "collection" }
如果您需要将数据转换为浮点数,那么执行此操作的唯一方法是迭代,因为 MongoDB 除了整数到字符串之外没有提供开箱即用的类型转换方法聚合 Cursor 对象并使用parseFloat 或Number 转换您的值,然后使用$set 运算符和bulkWrite() 方法更新您的文档以获得最大效率。
let requests = [];
cursor.forEach(doc => {
requests.push({
"updateOne": {
"filter": { "_id": doc._id },
"update": {
"$set": {
"data": doc.data,
"version": parseFloat(doc.version)
},
"$unset": { "person": " " }
}
}
});
if ( requests.length === 1000 ) {
// Execute per 1000 ops and re-init
db.collection.bulkWrite(requests);
requests = [];
}}
);
// Clean up queues
if(requests.length > 0) {
db.coll.bulkWrite(requests);
}
虽然聚合查询将在 MongoDB 3.4 或更高版本中完美运行,但我们从 MongoDB 3.2 向后最好的选择是使用 bulkWrite() 方法的 mapReduce。
var results = db.collection.mapReduce(
function() {
var v = this.version.split(".")[2];
emit(this._id, v.indexOf("-") > -1 ? "-"+v.replace(/\D+/g, '') : v)
},
function(key, value) {},
{ "out": { "inline": 1 } }
)["results"];
results 看起来像这样:
[
{
"_id" : ObjectId("57a98773cbbd42a2156260d8"),
"value" : "32"
},
{
"_id" : ObjectId("57a98773cbbd42a2156260d9"),
"value" : "-42"
}
]
从这里您使用之前的.forEach 循环来更新您的文档。
从 MongoDB 2.6 到 3.0,您将需要使用现已弃用的 Bulk() API 及其关联方法,如我的 answer here. 中所示