2017-03-15 20 views
0

一意の値を持っていないコレクションからドキュメントを削除します。私は、ユーザーがfooある場合を除き、重複する値を持つすべてのオブジェクトを検索し、削除したい MongoDBは、私がこのようなオブジェクトのコレクションを持っている

{"_id":"...", "user":"foo", "value":"a"}, // this one stays coz its user is foo 
{"_id":"...", "user":"bar", "value":"a"}, // remove this one 
{"_id":"...", "user":"baz", "value":"a"}, // remove this one 
{"_id":"...", "user":"qux", "value":"b"}, // this one has unique value so it doesn't get deleted 

JS mongoshellのアプローチはありますか?

+1

あなたはこれまでに何を試しましたか? – Searching

答えて

0

これは、mongoDBで重複を取得するのに要したものです。 aggregateは、調べるのに役立つ機能です。複数のパイプラインを適用して、必要な場所にアクセスできます。 aggregate

  1. 試合_idことと設定文書で見つかった各$_id(オリジナル)のカウントをインクリメントする予定ですvalue、によって
  2. グループにそれらをfooに等しくないすべてのユーザー。項目をdocIdsという配列にプッシュします。この新しいセットから
  3. は(より良い説明のためのドキュメントをチェックしてください)

これはあなたにvalueを複数回登場している文書を与える$> 1つの

  • アンワインドをカウントしているすべての行/ドキュメントを取得します。これらのドキュメントの削除操作は、結果セットに問題がなければ実行できます。私は手動でこれを実行していません...ご連絡ください..

    db.collection.aggregate([{ 
          $match: { 
           "user": { 
            $ne: "foo" 
           } 
          } 
         }, { 
          $group: { 
           _id: "$value", 
           docIds: { 
            $push: "$_id" 
           }, 
           count: { 
            $sum: 1 
           } 
          } 
         }, { 
          $match: "$count": { 
           $gt: 1 
          } 
         }, { 
          $unwind: $docIds 
         } 
        ]) 
    
  • 0

    私は(これはでないコードブロックを使用してこれを固定し[OK]を、これはテストされていませんが、ここで屋...これはデータベースと対話するためにマングースを使用して想定している...

    let values = []; 
    let deleteIds = []; 
    
    myModel.find({}).then(docs => { 
        docs.forEach(d => { 
         if (values.indexOf(d.value)) { 
          deleteIds.push(d._id); 
         } else { 
          values.push(d.value); 
         } 
        }) 
    
        deleteIds.forEach(id => { 
         myModel.findOneAndRemove({_id: id}); 
        }); 
    }); 
    
    +0

    このコードは300万レコードで動作しますか?それ以外の私はモンゴルのシェルソリューションは私のケースでより良く適合すると思う – Kunok

    +0

    はい、しかし、どのくらいの頻度でこのopをしたいですか? – wayofthefuture

    +0

    データベースを一度だけクリーニングする必要があります。 – Kunok

    0

    を行きますこの機能のための完全なコード):

    let query = { 
        user:targetedUser 
    } 
    let projection = { 
        _id:0, id:1, user:1 
    } 
    
    
    collection.find(query, projection) 
         .on('data', doc => { 
         collection.deleteMany({id:doc.id, user: {$not: new RegExp(targetedUser)}}) 
         }) 
         .on('end', _=> { 
         db.close() 
         }) 
    

    基本的にtargetedUser変数を使用すると、重複していると、その値と一致しない他のすべてを除去しながら維持したいオブジェクトの値です。それを見て、特定のユーザーのためにそれらを保持しながら、他のユーザーからすべての重複を削除します。

    これは非常に特殊なケースで、通常の問題では異なる場合があります。しかし、この答えのポイントは、このコードはすべてのRAMを食べるように見えるかもしれませんが、これまでに試した他の実装と比較して、300万レコードで20MB以上を要しませんでした。 。

    関連する問題