MongoDBにはコレクションがあります(約300万件のレコード)。サンプルレコードは次のようになります。
{ "_id" = ObjectId("50731xxxxxxxxxxxxxxxxxxxx"),
"source_references" : [
"_id" : ObjectId("5045xxxxxxxxxxxxxx"),
"name" : "xxx",
"key" : 123
]
}
同じsource_references.key
を持つコレクションに重複したレコードがたくさんあります。 (重複によって、source_references.key
ではなく_id
)。
source_references.key
に基づいて重複するレコードを削除したいので、各レコードをトラバースし、存在する場合はレコードを削除するコードをいくつかPHP)と書くことを考えています。
Mongo Internalコマンドラインで重複を削除する方法はありますか?
source_references.key
が重複レコードを識別することが確実な場合は、MongoDB 2.6以前の dropDups:true
インデックス作成オプションで一意のインデックスを確認できます。
db.things.ensureIndex({'source_references.key' : 1}, {unique : true, dropDups : true})
これにより、各source_references.key
値に対して最初の一意のドキュメントが保持され、重複キー違反の原因となる後続のドキュメントは削除されます。
重要な注意事項:
dropDups
オプションは MongoDB 3.0で削除 であったため、別のアプローチが必要になります。たとえば、次のように提案された集約を使用できます。 一意のキーを追加した後でもMongoDBがドキュメントを複製する .source_references.key
フィールドが欠落しているドキュメントは、null値を持つと見なされるため、キーフィールドが欠落している後続のドキュメントは削除されます。 sparse:true
インデックス作成オプションを追加して、source_references.key
フィールドを持つドキュメントにのみインデックスが適用されるようにすることができます。明らかな注意:データベースのバックアップを取り、意図しないデータ損失が心配な場合は、まずステージング環境でこれを試してください。
これは、MongoDB 3.2で使用した最も簡単なクエリです
db.myCollection.find({}, {myCustomKey:1}).sort({_id:1}).forEach(function(doc){
db.myCollection.remove({_id:{$gt:doc._id}, myCustomKey:doc.myCustomKey});
})
これを実行する前にcustomKey
にインデックスを付けて速度を上げます
@ Stennie'sは有効な答えですが、それが唯一の方法ではありません。実際、MongoDBマニュアルでは、その際に非常に慎重になるように求められています。他に2つのオプションがあります
以下に、もう少し「手動」で行う方法を示します。
基本的に、まず、興味のあるすべての一意のキーのリストを取得します。
次に、これらの各キーを使用して検索を実行し、その検索が1より大きい値を返す場合は削除します。
db.collection.distinct("key").forEach((num)=>{
var i = 0;
db.collection.find({key: num}).forEach((doc)=>{
if (i) db.collection.remove({key: num}, { justOne: true })
i++
})
});
pip install mongo_remove_duplicate_indexes
理解を深めるために、mongo_remove_duplicate_indexesのパッケージソースコードを確認してください。
十分なメモリがある場合は、scalaで次のようなことができます。
cole.find().groupBy(_.customField).filter(_._2.size>1).map(_._2.tail).flatten.map(_.id)
.foreach(x=>cole.remove({id $eq x})