最近在工作上遇到需要清理雞湯文中重復(fù)的數(shù)據(jù),網(wǎng)上搜了一下俺祠,有不少方案公给,有用程序去重的,有用唯一索引來控制的蜘渣,感覺都不是很方便淌铐,后來發(fā)現(xiàn)用下面這個(gè)非常方便;
db.Passages.aggregate([
{
$group:{_id:{content:'$content',endTime:'$endTime',startTime:'$startTime'},count:{$sum:1},dups:{$addToSet:'$_id'}}
},
{
$match:{count:{$gt:1}}
}
]).forEach(function(it){
it.dups.shift();
db.Passages.remove({_id: {$in: it.dups}});
});
下面來解析:
- 使用aggregate聚合查詢重復(fù)數(shù)據(jù)
- $group中是查詢條件蔫缸,根據(jù)content腿准、endTime、startTime字段來聚合相同的數(shù)據(jù)拾碌;
- $count用來統(tǒng)計(jì)重復(fù)出現(xiàn)的次數(shù)吐葱, $match來過濾沒有重復(fù)的數(shù)據(jù);
- $addToSet將聚合的數(shù)據(jù)id放入到dups數(shù)組中方便后面使用校翔;
- 查詢結(jié)果使用forEach進(jìn)行迭代id來刪除數(shù)據(jù)
- shift()作用是剔除隊(duì)列中第一條id弟跑,避免刪掉所有的數(shù)據(jù);
PS:注意函數(shù)的大小寫防症,mongoDB是嚴(yán)格區(qū)分大小寫的C霞!蔫敲!
今天發(fā)版本執(zhí)行腳本的時(shí)候發(fā)現(xiàn)在mongo2.4x的版本下面執(zhí)行報(bào)錯(cuò):
MongoDB shell version: 2.4.9
connecting to: 192.168.xxx.xxx:27017/xxx
Tue Apr 3 18:41:26.268 TypeError: Object [object Object] has no method 'forEach' at xxx.js:11
failed to load: xxx.js
先開始以為是2.4x版本如果沒有查到重復(fù)數(shù)據(jù)造成forEach報(bào)錯(cuò)饲嗽,加上try、catch手動(dòng)捕獲異常避免腳本執(zhí)行失敗奈嘿,后來檢查數(shù)據(jù)發(fā)現(xiàn)有重復(fù)數(shù)據(jù)的也依然進(jìn)異常了貌虾,這下就懵逼了,難道2.4x版本aggregat返回的數(shù)據(jù)跟3.x版本的還不一樣裙犹?
var list = db.Passages.aggregate([
{
$group:{_id:{content:'$content',endTime:'$endTime',startTime:'$startTime'},count:{$sum:1},dups:{$addToSet:'$_id'}}
},
{
$match:{count:{$gt:1}}
}
]);
print([JSON.stringify(list));
最后把查出的數(shù)據(jù)打印出來尽狠,發(fā)現(xiàn)返回的都是一個(gè)json對象不是數(shù)組榴鼎,2.4x版本的數(shù)據(jù)是放在reslut
字段下的,而3.x是放在·_batch·字段下(至于為什么可以直接forEach有待研究)晚唇,當(dāng)時(shí)心中一萬只xxx奔騰而過,抱怨歸抱怨bug還是要改的盗似,當(dāng)然就只能先判斷一下版本羅哩陕。
經(jīng)過反復(fù)修改測試,下面是最終修改結(jié)果赫舒。
var list = db.Passages.aggregate([
{
$group:{_id:{content:'$content',endTime:'$endTime',startTime:'$startTime'},count:{$sum:1},dups:{$addToSet:'$_id'}}
},
{
$match:{count:{$gt:1}}
}
]);
if(list._batch!=undefined){
print('v3.4....')
list.forEach(function(it){
it.dups.shift();
db.Passages.remove({_id: {$in: it.dups}});
});
}else{
print('v.2.4....')
list.result.forEach(function(it){
it.dups.shift();
db.Passages.remove({_id: {$in: it.dups}});
});
}