2012-05-22 12 views
7

の最後の要素の変更:更新操作で は、私がこのようなオブジェクトの構造を有する配列

{ 
    name: "...", 
    pockets: [ 
     { 
      cdate: "....", 
      items: [...] 
     } 
     ... 
    ] 
} 

を、私は最後のポケット項目の項目フィールドにいくつかのレコードを追加したいです。私がサブ文書にアクセスするのを知っている唯一の方法は、ドット表記を使うことですが、私が望むものを得ることはできません。だから、私はこれらのようなものを探しています:

  • pockets.-1.items
  • pockets.$last.items

は、それが最後の要素を変更することは可能ですか?はいの場合、どうですか?

+0

'items'を修正したいのですが、フェッチしないのですか? – paulmelnikow

+0

はい、あなたは正しいです。フェッチでは、$ slice演算子を使用できます。 – Muatik

+0

最後のポケットに合わせる方法がない限り、単純なアップデートではできないと私は確信しています。 – paulmelnikow

答えて

2

単一行のクエリを使用してこれを行う方法がわかりません。しかし、レコードを選択して更新し、保存することができます。

var query = <insert query here>; 
var mydocs = db.mycollection.find(query); 
for (var i=0 ; i<mydocs.length ; i++) { 
    mydocs[i].pockets[pockets.length-1].items.push('new item'); 
    db.mycollection.save(mydoc); 
} 
+3

これはスレッドセーフではない可能性があります。これは、別のプロセスが、検索の後と保存の前に配列を変更する可能性があるためです。 –

+0

@AsyaKamsky優秀なポイント...私は私の答えを更新します。 – McGarnagle

2

私はそれを原子的に行うことはできません。この機能をMongoDBに追加するには、requestがあります。

あなたアプリケーションコードでスレッドの安全性を確保することができる場合、あなたはおそらくp.itemsにポケット変数Pへの配列(つまり、ポケットから最後の要素を削除)してから$ addToSetからポップ$のシーケンスを使用することができます今、$ pをポケットに押し戻すことができます。しかし、アプリケーションで一度に1つのプロセスしか実行していないことを保証する方法がない場合、別のプロセスがそのステップの途中で配列を変更し、その更新を失う可能性があります。

「最新の場合は更新する」セマンティクスhereを参照すると、複数のスレッドの問題によって可能なレースを回避する別の方法が表示される場合があります。