2015-07-22 87 views
4

您好我有一個〜mongodb(複製)每個文檔43字段〜500萬文件。如何刪除重複的文件。我tryed從MongoDB刪除重複

db.testkdd.ensureIndex({ 
     duration : 1 , protocol_type : 1 , service : 1 , 
     flag : 1 , src_bytes : 1 , dst_bytes : 1 , 
     land : 1 , wrong_fragment : 1 , urgent : 1 , 
     hot : 1 , num_failed_logins : 1 , logged_in : 1 , 
     num_compromised : 1 , root_shell : 1 , su_attempted : 1 , 
     num_root : 1 , num_file_creations : 1 , num_shells : 1 , 
     num_access_files : 1 , num_outbound_cmds : 1 , is_host_login : 1 , 
     is_guest_login : 1 , count : 1 , srv_count : 1 , 
     serror_rate : 1 , srv_serror_rate : 1 , rerror_rate : 1 , 
     srv_rerror_rate : 1 , same_srv_rate : 1 , diff_srv_rate : 1 , 
     srv_diff_host_rate : 1 , dst_host_count : 1 , dst_host_srv_count : 1 , 
     dst_host_same_srv_rate : 1 , dst_host_diff_srv_rate : 1 , 
     dst_host_same_src_port_rate : 1 , dst_host_srv_diff_host_rate : 1 , 
     dst_host_serror_rate : 1 , dst_host_srv_serror_rate : 1 , 
     dst_host_rerror_rate : 1 , dst_host_srv_rerror_rate : 1 , lable : 1 
    }, 
    {unique: true, dropDups: true} 
) 

運行此代碼我得到一個錯誤「ERRMSG」:「從指數產生命名空間的名稱..

{ 
    "ok" : 0, 
    "errmsg" : "namespace name generated from index name \"project.testkdd.$duration_1_protocol_type_1_service_1_flag_1_src_bytes_1_dst_bytes_1_land_1_wrong_fragment_1_urgent_1_hot_1_num_failed_logins_1_logged_in_1_num_compromised_1_root_shell_1_su_attempted_1_num_root_1_num_file_creations_1_num_shells_1_num_access_files_1_num_outbound_cmds_1_is_host_login_1_is_guest_login_1_count_1_srv_count_1_serror_rate_1_srv_serror_rate_1_rerror_rate_1_srv_rerror_rate_1_same_srv_rate_1_diff_srv_rate_1_srv_diff_host_rate_1_dst_host_count_1_dst_host_srv_count_1_dst_host_same_srv_rate_1_dst_host_diff_srv_rate_1_dst_host_same_src_port_rate_1_dst_host_srv_diff_host_rate_1_dst_host_serror_rate_1_dst_host_srv_serror_rate_1_dst_host_rerror_rate_1_dst_host_srv_rerror_rate_1_lable_1\" is too long (127 byte max)", 
    "code" : 67 
} 

如何解決這個問題

回答

7

的? 「dropDups」索引創建的語法從MongoDB 2.6和removed in MongoDB 3.0開始已被「棄用」。在大多數情況下它不是一個好主意因爲「刪除」是任意的,任何「重複」都可以刪除。這意味着什麼被「刪除」可能不是你真正想要刪除的。

無論如何,您正遇到「索引長度」錯誤,因爲此處的索引鍵的值會更長。一般來說,在任何正常應用程序中,您都不是「爲了」索引43個字段。

如果你想從一個集合中刪除「重複」,那麼你最好的辦法是運行一個聚合查詢來確定哪些文檔包含「重複」數據,然後在該列表中循環刪除已經存在的「來自目標集合的「唯一」_id值。這可以通過"Bulk"操作來實現最大效率。

注意:我覺得很難相信,您的文件實際上包含43「獨一無二」的領域。很可能「你所需要的」是簡單地識別那些使文檔「獨一無二」的字段,然後按照流程概述如下:

var bulk = db.testkdd.initializeOrderedBulkOp(), 
    count = 0; 

// List "all" fields that make a document "unique" in the `_id` 
// I am only listing some for example purposes to follow 
db.testkdd.aggregate([ 
    { "$group": { 
     "_id": { 
      "duration" : "$duration", 
      "protocol_type": "$protocol_type", 
      "service": "$service", 
      "flag": "$flag" 
     }, 
     "ids": { "$push": "$_id" }, 
     "count": { "$sum": 1 } 
    }}, 
    { "$match": { "count": { "$gt": 1 } } } 
],{ "allowDiskUse": true}).forEach(function(doc) { 
    doc.ids.shift();  // remove first match 
    bulk.find({ "_id": { "$in": doc.ids } }).remove(); // removes all $in list 
    count++; 

    // Execute 1 in 1000 and re-init 
    if (count % 1000 == 0) { 
     bulk.execute(); 
     bulk = db.testkdd.initializeOrderedBulkOp(); 
    } 
}); 

if (count % 1000 != 0) 
    bulk.execute(); 

如果你有一個MongoDB的版本「低於2.6「,並且沒有批量操作,那麼您可以在循環內使用標準.remove()。還注意到.aggregate()不會在這裏返回遊標和循環必須更改爲:

db.testkdd.aggregate([ 
    // pipeline as above 
]).result.forEach(function(doc) { 
    doc.ids.shift(); 
    db.testkdd.remove({ "_id": { "$in": doc.ids } }); 
}); 

但一定要確保在你的文檔仔細看,只包括「公正」「獨一無二」的字段,你期望得到部分的分組_id。否則,你最終根本沒有刪除,因爲那裏沒有重複。

+0

@mohamedzajith嗯**錯誤實際上是告訴你該怎麼做。將「allowDiskUse」添加到管道中。這是用匯總方法記錄的。我還建議你「仍然」傳球的領域比實際構成「獨特」組合的領域更多。 –

+0

如何在mongo shell中添加** allowDiskUse ** – mohamedzajith

+0

@mohamedzajith在[documentation]中有清晰的示例(http://docs.mongodb.org/manual/reference/method/db.collection.aggregate/#perform-用於聚合選項的大排序操作與外部排序)。它們是在管道參數數組之後指定的。上面的例子。 –