2017-06-22 4 views
3

私は2つのコレクション(coll_1、coll_2)にそれぞれ100万個のドキュメントを持っています。2つのコレクションのすべてのドキュメントを何百万というドキュメントと比較し、MongoDBの3番目のコレクションにdiffを書き込む方法

これらの2つのコレクションは、同じデータソースから2つのバージョンのコードを実行することによって実際に作成されるため、2つのコレクションの文書数は同じですが、両方のコレクションの文書には、または異なる値を持つことができますが、両方のコレクションのドキュメントにはと同じprimary_key_idがインデックスされます。

私はこの

diffJSON(testObj1, testObj2); 

質問のように正常に動作デフ

db.system.js.save({ 
    _id: "diffJSON", value: 
    function(obj1, obj2) { 
     var result = {}; 
     for (key in obj1) { 
      if (obj2[key] != obj1[key]) result[key] = obj2[key]; 
      if (typeof obj2[key] == 'array' && typeof obj1[key] == 'array') 
       result[key] = arguments.callee(obj1[key], obj2[key]); 
      if (typeof obj2[key] == 'object' && typeof obj1[key] == 'object') 
       result[key] = arguments.callee(obj1[key], obj2[key]); 
     } 
     return result; 
    } 
}); 

取得するには、DBに保存されたこのjavascript関数があります。coll1とcoll2上diffJSONを実行する方法をし、 primary_key_idとともにcoll3にdiffJSON結果を出力します。

MongoDBの新機能で、JOINSがRDBMSと似たように動作しないことを理解しています。したがって、2つの比較ドキュメントを1つのコレクションにコピーしてからdiffJSON関数を実行する必要があります。

また、2つのコレクションのほとんどの時間(たとえば90%)のドキュメントは同じになります。差分があるドキュメントの約10%しか知りません。あなたが文書をdiffをするより良い方法を知っていれば、自由にしてください (しかし、実際のドキュメントは、あなたが規模を知っているだけのようにサイズが周り15Kである)

var testObj1 = { test:"1",test1: "2", tt:["td","ax"], tr:["Positive"] ,tft:{test:["a"]}}; 
var testObj2 = { test:"1",test1: "2", tt:["td","ax"], tr:["Negative"] }; 

:ここ

は簡単な例の文書であります提案する。

答えて

3

これを実現するには、単純なシェルスクリプトを使用できます。まずscript.jsという名前のファイルを作成し、その中にこのコードを貼り付けます。

このスクリプトで
// load previously saved diffJSON() function 
db.loadServerScripts(); 

// get all the document from collection coll1 
var cursor = db.coll1.find(); 

if (cursor != null && cursor.hasNext()) { 
    // iterate over the cursor 
    while (cursor.hasNext()){ 
    var doc1 = cursor.next(); 
    // get the doc with the same _id from coll2 
    var id = doc1._id; 
    var doc2 = db.coll2.findOne({_id: id}); 
    // compute the diff 
    var diff = diffJSON(doc2, doc1); 
    // if there is a difference between the two objects 
    if (Object.keys(diff).length > 0) { 
    diff._id = id; 
    // insert the diff in coll3 with the same _id 
    db.coll3.insert(diff); 
    } 
    } 
} 

私はあなたのPRIMARY_KEY_idフィールドであることを前提としています。あなたはこのようにシェルから

し、それを実行します。databaseName、コレクションcoll1coll2を含むデータベースで来ている

mongo --host hostName --port portNumber databaseName < script.js 

var testObj1 = { _id: 1, test:"1",test1: "2", tt:["td","ax"], tr:["Positive"] ,tft:{test:["a"]}}; 
var testObj2 = { _id: 1, test:"1",test1: "2", tt:["td","ax"], tr:["Negative"] }; 

スクリプトはcoll3で、次のドキュメントを保存します:

{ "_id" : 1, "tt" : { }, "tr" : { "0" : "Positive" } } 
0

このソリューションは、提案1の上に構築このサンプル文書(ちょうどあなたのドキュメントへ_idフィールドを追加しました)ため

フェリックス(私は彼にコメントするために必要な評判を持っていません)。

// load previously saved diffJSON() function 
db.loadServerScripts(); 

// get all the document from collection coll1 and coll2 
var cursor1 = db.coll1.find().sort({'_id': 1}); 
var cursor2 = db.coll2.find().sort({'_id': 1}); 

if (cursor1 != null && cursor1.hasNext() && cursor2 != null && cursor2.hasNext()) { 
    // iterate over the cursor 
    while (cursor1.hasNext() && cursor2.hasNext()){ 
    var doc1 = cursor1.next(); 
    var doc2 = cursor2.next(); 
    var pk = doc1._id 
    // compute the diff 
    var diff = diffJSON(doc2, doc1); 
    // if there is a difference between the two objects 

    if (Object.keys(diff).length > 0) { 
    diff._id = pk; 
    // insert the diff in coll3 with the same _id 
    db.coll3.insert(diff); 
    } 
    } 
} 

2つのカーソルがプライマリキーによってソートデータベース内のすべてのエントリをフェッチするために使用されている:私は、重要なパフォーマンスの向上をもたらし、彼のスクリプトにいくつかの小さな変更を加えました。これは非常に重要な側面であり、パフォーマンスの向上のほとんどをもたらします。主キーでソートされたドキュメントを検索することにより、主キーで正しく一致することを確認します。これは、2つのコレクションが同じデータを保持しているという事実に基づいています。

このようにして、coll1の各ドキュメントに対してcoll2を呼び出さないようにします。それは何か重要ではないように見えるかもしれませんが、我々はデータベースに多くのストレスをかける100万コールについて話しています。

もう1つの重要な前提は、プライマリキーフィールドが_idであることです。そうでない場合は、ユニークキーフィールドのインデックスを一意にすることが重要です。そうしないと、スクリプトは同じ主キーを持つドキュメントを不一致にする可能性があります。

関連する問題