2017-01-18 1 views
0

MongoDB 3.2.5を使用しています。 2つのコレクションがあり、どちらも約2百万のドキュメントを含んでいます。大規模なデータベースの別のコレクションからの参照がない文書を見つける

Devices 
{ 
    _id: xx 
} 

Interactions 
{ 
    _id: yy 
    StartDateTime: 2016-10-24 17:21:30.989Z 
    DeviceId: xx 
} 

相互作用から参照を持たないすべてのデバイスを検索したいと思います。私は以下のコードを試してみましたが、それは小さなDBで動作しますが、大きなDBでは失敗します。

var matches = db.Interactions.find({}, { DeviceId: 1 }); 
var devicesIds = []; 
matches.forEach(function(match) { devicesIds.push(match.DeviceId) }); 
var count = db.Devices.find({ "_id": { $nin : devicesIds } }).count(); 
print(count); 

これは、エラーメッセージがスローされます。

[thread1] Error: BufBuilder attempted to grow() to 134217728 bytes, past the 64MB limit.

私も試してみました:

db.Devices.aggregate([ 
    { 
     $lookup: 
     { 
      from: "Interactions", 
      localField: "_id", 
      foreignField: "DeviceId", 
      as: "matched_docs" 
     } 
    }, 
    { 
     $match: { "matched_docs": { $eq: [] } } 
    }, 
    { 
     $out: "TempDevicesNoInteraction" 
    } 
]); 

クエリの実行3時間が、まだ完了していません。私はそれをキャンセルする必要があります。以下のクエリと同じです:

var count = 0; 

db.Devices.find().forEach(function(myDoc) { 
    var cursor = db.Interactions.find({DeviceId: myDoc._id}); 
    if(!cursor.hasNext()) { 
     count = count + 1; 
    } 
}); 

print(count); 

私はMongoDBを初めて利用しています。

答えて

0

Interactionsコレクションの[DeviceId]フィールドにインデックスが設定されていますか? $ルックアップ演算子は、あなたの200万文書のそれぞれについて、(200万の文書上)collectionscanを行うと ていない場合は集計....

だから、「デバイスID」にインデックスがあることを確認してください。

このクエリを頻繁に実行する予定ですか?答えが「はい」の場合、$out operatorを使用して、集計結果を新しいコレクションに保存できます。この方法では、最初の塗りつぶしに時間がかかることがありますが、そのデータに対する各クエリはうまく機能します。しかしそれはあなたがしなければならない考慮事項です。

+0

Interactionsコレクションの "DeviceId"フィールドにインデックスがありません。私は、インデックスを追加した後、集計コマンドは正常に実行されます。 – Nat

関連する問題