2012-04-11 10 views
1

私のMongoDB内のいくつかのオブジェクトを修正しようとすると、奇妙な動作が起こりました。言語コード(lc)をmayからmsaに変更しようとしていますが、テキストと言語コードに固有のインデックスがあります。重複したキーを更新しようとしましたが、db.XYZ.updateに失敗しました。

E11000 duplicate key error index: jerome5.Unit.$t_1_lc_1 dup key: { : "laluan", : "msa" } 
:その後で失敗し、

db.Unit.find({lc: "may"}, {"t":1}).limit(1000).forEach(function(obj) { 
    try { 
     db.Unit.update({ _id: obj._id }, {$set : { "lc": "msa"}}); 
     print('Changed :' + obj.t + '#' + obj._id); 
    } catch (err) { 
     print(err); 
    } 
}); 

これは、オブジェクトの多くをプリントアウト動作するようだ:私がしようと

db.Unit.count({lc: "may"}); 

ザ・:{t:1, lc:1}

まず私はカウントを取得します

今、私は失敗が正しく更新される前の試合を期待していたが、 nsはまったく同じ番号です。

私はJavascriptで明白なことを忘れましたか?

更新:例外をスローせずに印刷するオブジェクトのいくつかは重複しているように見えます。だから、エラーがスローされる前に(私はジャーナリングが有効になっている)いくつかの遅延があるように見えます。これは正常な動作ですか?

答えて

6

短い答えは、問題がJSコードであることです。

Mongoのアップデートは、デフォルトでfireとforgetです。重複したキーのために個々のアップデートが失敗しても、 "try"文は正常に完了し、 "catch"セクションのコードは決して消えません。実行される。 forEachループが終了するとJSシェルはdb.getLastError()を返し、操作が成功するとnullを返すため、「catch」コードが実行されているように見えることがあります。 GetLastErrorは、ここでのドキュメントで説明されています http://www.mongodb.org/display/DOCS/getLastError+Command

これはおそらく最良の例を通じて説明している:我々は実行しようとしている

> db.unit.save({_id:0, lc: "may", t:0}) 
> db.unit.ensureIndex({t:1, lc:1}, {unique:true}) 
> for(var i=1; i<10; i++){db.unit.save({_id:i, lc: "may", t:i})} 
> db.unit.find() 
{ "_id" : 0, "lc" : "may", "t" : 0 } 
{ "_id" : 1, "lc" : "may", "t" : 1 } 
{ "_id" : 2, "lc" : "may", "t" : 2 } 
{ "_id" : 3, "lc" : "may", "t" : 3 } 
{ "_id" : 4, "lc" : "may", "t" : 4 } 
{ "_id" : 5, "lc" : "may", "t" : 5 } 
{ "_id" : 6, "lc" : "may", "t" : 6 } 
{ "_id" : 7, "lc" : "may", "t" : 7 } 
{ "_id" : 8, "lc" : "may", "t" : 8 } 
{ "_id" : 9, "lc" : "may", "t" : 9 } 
> 

は、単純な収集、および一意のインデックスを作成することができますスクリプトを使用して、「may」の値をすべて「msa」に変更します。

> db.unit.update({_id: 3}, {"lc" : "msa", "t" : 4 }) 
> db.unit.update({_id: 6}, {"lc" : "msa", "t" : 5 }) 
> db.unit.find() 
{ "_id" : 0, "lc" : "may", "t" : 0 } 
{ "_id" : 1, "lc" : "may", "t" : 1 } 
{ "_id" : 2, "lc" : "may", "t" : 2 } 
{ "_id" : 3, "lc" : "msa", "t" : 4 } 
{ "_id" : 4, "lc" : "may", "t" : 4 } 
{ "_id" : 5, "lc" : "may", "t" : 5 } 
{ "_id" : 6, "lc" : "msa", "t" : 5 } 
{ "_id" : 7, "lc" : "may", "t" : 7 } 
{ "_id" : 8, "lc" : "may", "t" : 8 } 
{ "_id" : 9, "lc" : "may", "t" : 9 } 
> 

私たちのスクリプトは_id文書当たったとき:4:4と_id:5を、私たちは前に、これまで「MSA」はインデックスに重複する値を作成する「こと」のいくつかの値を変更し、いくつかの変更を行うことができます"lc"の値を "may"に変更することはできません。これは、インデックスに重複したエントリが作成されるためです。

スクリプトのバージョンを実行できます。あなたが見ることができるように

db.unit.find({lc: "may"}, {"t":1}).limit(1000).forEach(function(obj) { 
    try { 
     print("Found _id: " + obj._id); 
     db.unit.update({ _id: obj._id }, {$set : { "lc": "msa"}}); 
     if(db.getLastError() == null){ 
      print('Changed t :' + obj.t + ' _id : ' + obj._id); 
     } 
     else{ 
      print("Unable to change _id : " + obj.id + " because: " + db.getLastError()) 
     } 
    } catch (err) { 
     print("boo"); 
     print(err); 
    } 
}); 

Found _id: 0 
Changed t :0 _id : 0 
Found _id: 1 
Changed t :1 _id : 1 
Found _id: 2 
Changed t :2 _id : 2 
Found _id: 4 
Unable to change _id : undefined because: E11000 duplicate key error index: test.unit.$t_1_lc_1 dup key: { : 4.0, : "msa" } 
Found _id: 5 
Unable to change _id : undefined because: E11000 duplicate key error index: test.unit.$t_1_lc_1 dup key: { : 5.0, : "msa" } 
Found _id: 7 
Changed t :7 _id : 7 
Found _id: 8 
Changed t :8 _id : 8 
Found _id: 9 
Changed t :9 _id : 9 
> 

は、「ブー」は印刷されませんでした、「キャッチ」のコードが実行されなかったため、2つのレコードが更新できませんでしたにもかかわらず:私はそれをより詳細にするために、いくつかの余分な行を追加しています。技術的には、update()は失敗しませんでした。重複したインデックスエントリのためにドキュメントを変更できず、その旨のメッセージが生成されました。

変更可能なすべてのレコードが正常に変更されました。スクリプトを再度実行している場合

> db.unit.find() 
{ "_id" : 0, "lc" : "msa", "t" : 0 } 
{ "_id" : 1, "lc" : "msa", "t" : 1 } 
{ "_id" : 2, "lc" : "msa", "t" : 2 } 
{ "_id" : 3, "lc" : "msa", "t" : 4 } 
{ "_id" : 4, "lc" : "may", "t" : 4 } 
{ "_id" : 5, "lc" : "may", "t" : 5 } 
{ "_id" : 6, "lc" : "msa", "t" : 5 } 
{ "_id" : 7, "lc" : "msa", "t" : 7 } 
{ "_id" : 8, "lc" : "msa", "t" : 8 } 
{ "_id" : 9, "lc" : "msa", "t" : 9 } 

は、次の出力が生成されます。

Found _id: 4 
Unable to change _id : undefined because: E11000 duplicate key error index: test.unit.$t_1_lc_1 dup key: { : 4.0, : "msa" } 
Found _id: 5 
Unable to change _id : undefined because: E11000 duplicate key error index: test.unit.$t_1_lc_1 dup key: { : 5.0, : "msa" } 
E11000 duplicate key error index: test.unit.$t_1_lc_1 dup key: { : 5.0, : "msa" } 
> 

あなたは、最後のエラーメッセージが重複して印刷して見ることができるように:私たちは私たちのスクリプトでそれを印刷したときに一度、そして再びスクリプトが終了したとき。

この応答の冗長性を許してください。これにより、getLastErrorについての理解が深まり、操作がJSシェルでどのように実行されることが期待されます。

スクリプトは、try/catch文なしで再書き込み、単純に更新することができませんでした任意の文書の_idsプリントアウトすることができます。

db.unit.find({lc: "may"}, {"t":1}).limit(1000).forEach(function(obj) { 
    print("Found _id: " + obj._id); 
    db.unit.update({ _id: obj._id }, {$set : { "lc": "msa"}}); 
    if(db.getLastError() == null){ 
     print('Changed t :' + obj.t + ' _id : ' + obj._id); 
    } 
    else{ 
     print("Unable to change _id : " + obj.id + " because: " + db.getLastError()) 
    } 
}); 
+1

おかげでマルク、このような与えるために時間を割いての明確な応答。 'db.getLastError()'の例はまさに私が必要としていたものです! –

関連する問題