2012-12-28 15 views
10

MongoDBでupsertを使用してドキュメント内の単一フィールドを更新しようとしています。問題は、MongoDBがupsert操作ですべてのフィールドを置換するか、またはフィールドのサブセットを挿入する、つまり実際に更新するよりも多くのフィールドを挿入できないことがわかります。Mongodb upsertは選択されたフィールドのみを更新しますが、すべてを挿入します

私がやりたいことは以下の通りです:

  • 私は、単一の一意の値
  • 文書がすでに存在する場合は、唯一のタイムスタンプ値が(「lastseen」それを呼び出すことができます)を照会がに更新され、新しい値
  • ドキュメントが存在しない場合は、その寿命の間、静的に保つべき異なるキーと値のペアの長いリストを追加します。

説明します:

を「名前が」が見つかりされていますが、「名前」が見つからない場合、それは唯一の「name」+「を挿入する場合は、この例では、私の理解から「lastseen」日付を更新してしまうlastseen '

db.somecollection.update({name: "some name"},{ $set: {"lastseen": "2012-12-28"}}, {upsert:true}) 

私は2番目の引数に複数のフィールド(キー/値のペア)を追加し、$セットを落とした場合は、すべてのフィールドが更新に置き換えられるだろうが、挿入時に所望の効果を持っているでしょう。挿入するときにだけ操作を実行するために、$ insertなどのようなものはありますか?

  • 正しい更新動作が、ドキュメントが
  • 存在しない場合は必要なフィールドのサブセットのみで文書を挿入します:

    は、だから、私は、次のいずれかを得ることができるように私には思えます

  • 正しい挿入動作ですが、文書が既に存在する場合は既存のフィールドをすべて上書きします

私の理解は正しいですか?もしそうなら、これは単一の操作で解決することが可能ですか?

+1

を持っているこれらのキーと値のペアがアップサートの検索句で使用することができない理由はありますか? – Sammaye

+0

その理由は、その時点での値を知っているフィールドが1つしかないからです。フィールドの正確なコンボが一致しない場合、クエリで0ヒットを返さないようにします。私が値を知っている唯一のフィールドは、その新しい挿入物か更新かを決定します。 – agnsaft

答えて

27

のMongoDB 2.4は$setOnInsert

db.somecollection.update(
    {name: "some name"}, 
    { 
     $set: { 
      "lastseen": "2012-12-28" 
     }, 
     $setOnInsert: { 
      "firstseen": <TIMESTAMP> # set on insert, not on update 
     } 
    }, 
    {upsert:true} 
) 
8

これには、2.3で解決されている機能要求(https://jira.mongodb.org/browse/SERVER-340)があります。奇数のリリースは実際にはdevのリリースですので、これは2.4安定しています。

現在、これを行うには現在の安定版には実際の方法はありません。私は唯一の方法は実際に3つの条件付きクエリatmを実行することです:1行を確認するために、その後ifを挿入または更新する。

私はあなたがここでロックするのに本当の問題があったとすれば、あなたは単独のJSでこの機能を実行できますが、それは悪いことですが、このアップデートを単一のスレッドにロックするでしょう。

+0

ありがとう。私は実際にそのような情報を探すためにJiraで探していましたが、明らかに私はそれを見逃しました。 – agnsaft

関連する問題