61

私は 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 コマンドラインで重複を削除する方法はありますか?

4

8 に答える 8

80

この回答は廃止されました。このdropDupsオプションはMongoDB 3.0で削除されたため、ほとんどの場合、別のアプローチが必要になります。たとえば、MongoDB duplicate documents even after added unique key で提案されているように、集計を使用できます。

source_references.keyが重複レコードを特定していることが確実なdropDups:true場合は、MongoDB 2.6 以前でインデックス作成オプションを使用して一意のインデックスを確保できます。

db.things.ensureIndex({'source_references.key' : 1}, {unique : true, dropDups : true})

これにより、各値の最初の一意のドキュメントが保持されsource_references.key、重複キー違反の原因となる後続のドキュメントが削除されます。

重要な注意: フィールドが欠落しているドキュメントはnullsource_references.key値を持つと見なされるため、キー フィールドが欠落している後続のドキュメントは削除されます。インデックス作成オプションを追加して、インデックスがフィールドを持つドキュメントにのみ適用されるようにすることができます。sparse:truesource_references.key

明らかな注意: データベースのバックアップを作成し、意図しないデータ損失が懸念される場合は、最初にステージング環境でこれを試してください。

于 2012-11-02T07:20:40.533 に答える
67

これは、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これを実行する前にインデックスを作成して速度を上げます

于 2016-03-19T07:44:40.600 に答える
10

@Stennie's は有効な回答ですが、唯一の方法ではありません。実際、MongoDB のマニュアルでは、これを行う際には非常に注意するように求められています。他に2つのオプションがあります

  1. Map Reduceを使用して MongoDB に任せる
  2. プログラムで行うと、効率が低下します。
于 2012-11-02T07:28:20.007 に答える
8

これは、もう少し「手動」の方法です。

基本的に、まず、関心のあるすべての一意のキーのリストを取得します。

次に、これらの各キーを使用して検索を実行し、その検索で 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++
      })
    });
于 2017-08-23T12:51:15.710 に答える
2

十分なメモリがある場合は、scala で次のようなことができます。

cole.find().groupBy(_.customField).filter(_._2.size>1).map(_._2.tail).flatten.map(_.id)
.foreach(x=>cole.remove({id $eq x})
于 2016-12-12T16:02:32.680 に答える
1

pip install mongo_remove_duplicate_indexes

  1. 任意の言語でスクリプトを作成する
  2. コレクションを反復処理する
  3. 新しいコレクションを作成し、一意のセットをtrueにしてこのコレクションに新しいインデックスを作成します。このインデックスはインデックスと同じでなければならないことに注意してください。元のコレクションから同じ名前の重複を削除したい場合は、ex-uがコレクションゲームを持っています。コレクションには、削除したい重複を含むフィールド ジャンルがあるので、新しいコレクションを作成するだけです db.createCollection("cname") 新しいインデックス db.cname.createIndex({'genre':1},unique:1) を作成します似たようなジャンルのドキュメントを挿入すると、最初にのみ受け入れられ、他のものは重複キーエラーで拒否されます
  4. 受け取ったjson形式の値を新しいコレクションに挿入し、ex pymongo.errors.DuplicateKeyErrorの例外処理を使用して例外を処理するだけです

理解を深めるために、mongo_remove_duplicate_indexes のパッケージ ソース コードを確認してください。

于 2016-11-02T18:50:32.123 に答える