1. 程式人生 > >mongodb去除重複的資料(二)

mongodb去除重複的資料(二)

前天因為工作需要,開始著手對資料庫中兩千多萬的資料中其中一個欄位重複的資料進行去重。原本使用一些測試的資料測試後,前天寫的那個方法是可行的,但是當面對這個兩千萬的真實資料時,我卻發現這方法有些不頂用了,最終只好又經過若干次的嘗試,總算成功去重。最終總結一下整個過程:1、這個方法就是上一篇所講的,利用mongodb的遊標dbcursor和while迴圈的方式。
var res=db.test.find();
while(res.hasNext()){
      var res1=db.test.find(); 
      var re=res.next();
      while(res1.hasNext()){
              var re1=res1.next();
              if(re.age==re1.age){ 
                   db.test.remove({"age":re1.age}); 
               }
       } 
       db.test.insert(re); 
}

      原本我用了10000調資料進行測試,迴圈完畢後,就如預期一樣只剩下1條資料。但是面對兩千萬的資料後,執行到一半就報錯,並且一直卡在那裡。      我也不知道這情況究竟算是正常還是不正常,反正是等了半天的時間還是卡在那裡,整個集合的資料也沒有任何的變化。      我想大概是一次性處理的資料太多了吧,我的迴圈那樣執行下去,就需要迴圈兩千萬乘以兩千萬次,這個次數是在國語龐大,於是只好採取迂迴的措施,把兩千萬拆分成20個集合,一個集合只裝一百萬。      但是即便是一百萬的資料,當我在執行這個方法時,還是卡在了那裡。 於是我不禁就想,難到我要把20個集合再拆分成四十個集合,一個只裝五十萬?      四十個集合,這工作量貌似有點太大,我選擇無奈的放棄。
2、第一種方法失敗的情況下,我只好另尋他途,然後便想到了唯一索引的方法。    唯一索引的dropDups可以在建立索引時刪除重複的資料,我想這個總應該是可行的吧。然而事實卻證明我還是錯了,最終還是以失敗告終。    在我執行如下方法建立唯一索引的時候,又是屢屢報錯,並給我意外退出
db.alarm1.ensureIndex({"msgContent":1},{"unique":true,dropDups:true})
  直接在建立索引的時候刪除資料無法達到目的,我只好再次採用迂迴的方式,在一個全新的空集合中建立一個索引 :
 db.alarmBack.ensureIndex({"msgContent":1},{"unique":true})

    然後再把資料重新的匯入到這個已經存在了唯一索引的集合中,我想應該可以了吧。    但是,無奈的是,又失敗了!    因為我從生產資料庫匯出的資料用了mongodump的方式,所以匯入的時候也用的mongorestore的方式,而這個方式實際上是恢復資料,在恢復資料的同時,連索引也一起恢復了。    最讓我抓狂的是,恢復索引也就罷了,竟然還在恢復的時候把我建的唯一索引給幹掉了!這樣一來,唯一索引沒了,自然無法達到去重的目的,方法再次以失敗告終。    我不知道mongodump和mongorestore是否有相關引數可以指定不要索引,有空了一定要試一下(太坑了吧)。3、上述兩個方法都失敗了,第二個方法失敗的同時,我就想到要試一下另外一種匯入和匯出的方法:mongoimport和mongoexport。    我隱約記得這兩個方法匯入匯出的時候速度好像比mongodump和mongorestore慢,但是現在沒有辦法的情況下只好一試。    但是事實證明這個方法在這種情況下居然可行,最終我使用第二種方法中的第二種方式,先在空白集合中建一個唯一索引,然後匯入要去重的資料,成功的對這兩千多萬的資料去重。    不過真的是慢啊,單純的匯入,我用mongodump連mongoimport一半的時間都沒用到,不知道是否是因為姿勢不對,暫且也不想去管它了!    任務結束,但是心中還留下一些疑問,我想如果第二種方法中我匯出的元資料是沒有索引的,那麼當我匯入的時候,不知道它是否還會把我原本的唯一索引幹掉;還有就是,或許直接用java程式碼處理匯出的檔案也可以,甚至可能更快,不過暫時有別的事情,也就不做嘗試了。