web-dev-qa-db-ja.com

Robomongo:$ groupのメモリ制限を超えました

私はスクリプトを使用してmongoの重複を削除します。テストとして使用した10個のアイテムを持つコレクションで機能しましたが、600万個のドキュメントを持つ実際のコレクションに使用するとエラーが発生します。

これは、Robomongoで実行したスクリプトです(現在は Robo 3T として知られています)。

var bulk = db.getCollection('RAW_COLLECTION').initializeOrderedBulkOp();
var count = 0;

db.getCollection('RAW_COLLECTION').aggregate([
  // Group on unique value storing _id values to array and count 
  { "$group": {
    "_id": { RegisterNumber: "$RegisterNumber", Region: "$Region" },
    "ids": { "$Push": "$_id" },
    "count": { "$sum": 1 }      
  }},
  // Only return things that matched more than once. i.e a duplicate
  { "$match": { "count": { "$gt": 1 } } }
]).forEach(function(doc) {
  var keep = doc.ids.shift();     // takes the first _id from the array

  bulk.find({ "_id": { "$in": doc.ids }}).remove(); // remove all remaining _id matches
  count++;

  if ( count % 500 == 0 ) {  // only actually write per 500 operations
      bulk.execute();
      bulk = db.getCollection('RAW_COLLECTION').initializeOrderedBulkOp();  // re-init after execute
  }
});

// Clear any queued operations
if ( count % 500 != 0 )
    bulk.execute();

これはエラーメッセージです。

Error: command failed: {
    "errmsg" : "exception: Exceeded memory limit for $group, but didn't allow external sort. Pass allowDiskUse:true to opt in.",
    "code" : 16945,
    "ok" : 0
} : aggregate failed :
_getErrorWithCode@src/mongo/Shell/utils.js:23:13
doassert@src/mongo/Shell/assert.js:13:14
assert.commandWorked@src/mongo/Shell/assert.js:266:5
DBCollection.prototype.aggregate@src/mongo/Shell/collection.js:1215:5
@(Shell):1:1

だから私はallowDiskUse:trueを設定する必要がありますか?スクリプトのどこでそれを行うのですか?これを行うのに問題はありますか?

17
kadzu
{ allowDiskUse: true } 

集約パイプラインの直後に配置する必要があります。

コードでは、これは次のようになります。

db.getCollection('RAW_COLLECTION').aggregate([
  // Group on unique value storing _id values to array and count 
  { "$group": {
    "_id": { RegisterNumber: "$RegisterNumber", Region: "$Region" },
    "ids": { "$Push": "$_id" },
    "count": { "$sum": 1 }      
  }},
  // Only return things that matched more than once. i.e a duplicate
  { "$match": { "count": { "$gt": 1 } } }
], { allowDiskUse: true } )
38
Atish

大きなデータがある場合は、グループの前に一致を使用することを常にお勧めします。グループの前に一致を使用している場合、この問題は発生しません。

db.getCollection('sample').aggregate([
   {$match:{State:'TAMIL NADU'}},
   {$group:{
       _id:{DiseCode:"$code", State:"$State"},
       totalCount:{$sum:1}
   }},

   {
     $project:{
        Code:"$_id.code",
        totalCount:"$totalCount",
        _id:0 
     }   

   }

])

一致することなくこの問題を本当に克服した場合、解決策は{ allowDiskUse: true }

MongoDB Docsから

$ groupステージには、100メガバイトのRAMの制限があります。デフォルトでは、ステージがこの制限を超えると、$ groupはエラーを生成します。ただし、大きなデータセットの処理を許可するには、allowDiskUseオプションをtrueに設定して、$ group操作が一時ファイルに書き込むことを有効にします。詳細については、db.collection.aggregate()メソッドおよびaggregateコマンドを参照してください。

0
Sercan Ozdemir