1 背景
由于某些原因,上线新功能时-支持多数据中心(各数据中心的数据会双向同步),为了方便,更新数据库脚本写的过于简单,导致整个库部分数据洗脏。
数据库object表数据片段:
表简要说明:
sourceName数据中心来源标识,由数据库同步中间件打标识。
dataCenterId数据中心标识,有业务层落库,说明业务操作所在的数据中心。
_id | sourceName | dataCenterId |
abc123xxx01 | area01:cccd1811ed9161c94c7e05b7bb01 | master |
abc123xxx02 | master:cccd1811ed9161c94c7e05b7bb02 | master |
abc123xxx03 | master:cccd1811ed9161c94c7e05b7bb03 | master |
...... |
执行的SQL:
db.getCollection("object").update({}, {$set: {"dataCenterId": "master"}},false,true);
以上SQL将表中标红的数据更新为master,而正确的值应该为area01。
2 目的
根据sourceName的前缀更新dataCenterId,以达到清洗目的。
3 解决办法
db.object.find({$where:function () {
var result = this.sourceName.startsWith(this.dataCenterId);
if(result){
return false;
}else{
return true;
}
}
}).forEach(function(item) {
var arr = item.sourceName.split(':');
const newValue = arr[0];
item.dataCenterId = newValue;
db.object.save(item);
});
清洗后的object表数据片段:
_id | sourceName | dataCenterId |
abc123xxx01 | area01:cccd1811ed9161c94c7e05b7bb01 | area01 |
abc123xxx02 | master:cccd1811ed9161c94c7e05b7bb02 | master |
abc123xxx03 | master:cccd1811ed9161c94c7e05b7bb03 | master |
...... |
5 注意
$where操作符功能强大而且灵活,上述数据库清洗过程可以完美说明灵活这一点。他可以使用任意的JavaScript作为查询的一部分,包含JavaScript表达式的字符串或者JavaScript函数。
非常必要时,建议避免使用"$Where"査询,每个文档都要从BSON转换成JavaScript对象,然后通过"$where"的表达式来运行,还不能利用索引。因此它们在速度上要比常规査询慢。