2016-02-29 74 views
6

"contact_id"というフィールドを持つコレクションがあります。 私のコレクションでは、私はこのキーで重複したレジスタを持っています。MongoDBで重複を削除します

重複を削除して1つのレジスタにすることはできますか?

私は3.2

おかげ

答えて

18

はい、dropDupsはうまく行っていません。しかし、あなたは間違いなく少しの努力で目標を達成することができます。

重複する行をすべて見つけて、最初のものを除くすべてを削除する必要があります。

db.dups.aggregate([{$group:{_id:"$contact_id", dups:{$push:"$_id"}, count: {$sum: 1}}}, 
{$match:{count: {$gt: 1}}} 
]).forEach(function(doc){ 
    doc.dups.shift(); 
    db.dups.remove({_id : {$in: doc.dups}}); 
}); 

あなたはdoc.dups.shift()は、アレイから _id最初を削除してから、DUPのアレイ内の残りの_idsですべての文書を削除します見ての通り。

上記のスクリプトはすべての重複文書を削除します。

+0

をdedup.js私が働いていた場合、コメントしようと戻ります!ありがとう – Jhonathan

+0

いいですね。それがどうなるか教えてください。 – Saleem

+0

こんにちは。部分的に働いた。 小さなコレクションを入れるとうまく動作します。 しかし、大きなコレクションでデータベースをロックすると、他のクエリはタイムアウトになります。 – Jhonathan

0
を使用していた機能dropDupsは、もはやMongoDBの3.xでは提供されていますので、

db.PersonDuplicate.ensureIndex({"contact_id": 1}, {unique: true, dropDups: true}) 

しかし、うまくいきませんでした:

私はすでに試しました

多分、tmpColectionを作成し、ユニークなインデックスを作成し、ソースからデータをコピーして、最後のステップがスワップ名になるようにしてください。

その他のアイデア、私は(アグリゲーションを使用して)配列にインデックスを倍増取得することであり、その後、真または1

var itemsToDelete = db.PersonDuplicate.aggregate([ 
{$group: { _id:"$_id", count:{$sum:1}}}, 
{$match: {count: {$gt:1}}}, 
{$group: { _id:1, ids:{$addToSet:"$_id"}}} 
]) 

に設定justOneパラメータでremove()メソッドを呼び出しスルーループと作りましたループスルーID配列 はあなたにとってこの意味ですか?

5

これはmongod 3+にとっても良いパターンです。これは、本当に大きなコレクションで起こる可能性のあるメモリを実行しないことを保証します。あなたは、dedup.jsファイルにこれを保存し、それをカスタマイズし、を使用して目的のデータベースに対してそれを実行することができます:localhostとモンゴ:27017/YOURDBは

var duplicates = []; 

db.runCommand(
    {aggregate: "YOURCOLLECTION", 
    pipeline: [ 
     { $group: { _id: { DUPEFIELD: "$DUPEFIELD"}, dups: { "$addToSet": "$_id" }, count: { "$sum": 1 } }}, 
     { $match: { count: { "$gt": 1 }}} 
    ], 
    allowDiskUse: true } 
) 
.result 
.forEach(function(doc) { 
    doc.dups.shift(); 
    doc.dups.forEach(function(dupId){ duplicates.push(dupId); }) 
}) 
printjson(duplicates); //optional print the list of duplicates to be removed 

db.YOURCOLLECTION.remove({_id:{$in:duplicates}}); 
関連する問題