首先获取集合中所有键的明确列表,使用这些键作为查询基础并使用批量API操作进行有序批量更新。更新语句使用$unset
运算符删除字段。
通过Map-Reduce
可以获得您需要组装查询的不同密钥列表的机制。下面精简操作将填充单独收集的所有键作为_id值:
mr = db.runCommand({
"mapreduce": "my_collection",
"map" : function() {
for (var key in this) { emit(key, null); }
},
"reduce" : function(key, stuff) { return null; },
"out": "my_collection" + "_keys"
})
要获得所有动态密钥列表,在结果集合运行不同:
db[mr.result].distinct("_id")
// prints ["_id", "year", "year_comment", ...]
现在根据上面的列表,您可以通过创建一个将其属性设置为循环的对象来组装您的查询。通常情况下您的查询都会有这样的结构:
var keysList = ["_id", "year", "year_comment"];
var query = keysList.reduce(function(obj, k) {
var q = {};
q[k] = "";
obj["$or"].push(q);
return obj;
}, { "$or": [] });
printjson(query); // prints {"$or":[{"_id":""},{"year":""},{"year_comment":""}]}
然后,您可以使用Bulk API
(可与MongoDB的2.6及以上),作为简化与上面的查询性能更好的更新的方式。总体而言,你应该能有一些工作为:
var bulk = db.collection.initializeOrderedBulkOp(),
counter = 0,
query = {"$or":[{"_id":""},{"year":""},{"year_comment":""}]},
keysList = ["_id", "year", "year_comment"];
db.collection.find(query).forEach(function(doc){
var emptyKeys = keysList.filter(function(k) { // use filter to return an array of keys which have empty strings
return doc[k]==="";
}),
update = emptyKeys.reduce(function(obj, k) { // set the update object
obj[k] = "";
return obj;
}, { });
bulk.find({ "_id": doc._id }).updateOne({
"$unset": update // use the $unset operator to remove the fields
});
counter++;
if (counter % 1000 == 0) {
// Execute per 1000 operations and re-initialize every 1000 update statements
bulk.execute();
bulk = db.collection.initializeOrderedBulkOp();
}
})
它只从第一行删除空的项目,但剩下的其他地方是空的项目。我仍然试图找出问题所在。 shell写道:[object Object],[object Object],[object Object] ... –
使用这个函数:print(tojson(result));问题解决了。 –
@FerencStraub上面的代码片段工作得很好剥离结果中的空值字段 –