15

MongoDB で upsert を使用して、ドキュメント内の単一のフィールドが見つかった場合に更新するか、多数のフィールドを持つ新しいドキュメント全体を挿入しようとしています。問題は、MongoDB がアップサート操作ですべてのフィールドを置換するか、フィールドのサブセットを挿入するように見えることです。つまり、実際に更新するよりも多くのフィールドを挿入することはできません。

私がやりたいことは次のとおりです。

  • 単一の一意の値を照会します
  • ドキュメントが既に存在する場合、タイムスタンプ値 (「lastseen」と呼びましょう) のみが新しい値に更新されます。
  • ドキュメントが存在しない場合は、残りの寿命の間静的である必要があるさまざまなキーと値のペアの長いリストを追加します。

説明しましょう:

この例では、私の理解では、「name」が見つかった場合は「lastseen」の日付が更新されますが、「name」が見つからない場合は「name」+「lastseen」のみが挿入されます。

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

2 番目の引数にさらにフィールド (キーと値のペア) を追加し、$set を削除すると、すべてのフィールドが更新時に置き換えられますが、挿入時に望ましい効果が得られます。挿入時にのみ操作を実行する $insert などのようなものはありますか?

したがって、次のいずれかしか取得できないようです。

  • 正しい更新動作ですが、ドキュメントが存在しない場合は、目的のフィールドのサブセットのみを含むドキュメントを挿入します
  • 正しい挿入動作ですが、ドキュメントが既に存在する場合、既存のすべてのフィールドが上書きされます

私の理解は正しいですか?もしそうなら、これは1回の操作で解決できますか?

4

2 に答える 2

38

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}
)
于 2013-04-11T16:01:18.773 に答える
8

これに対する機能リクエスト ( https://jira.mongodb.org/browse/SERVER-340 ) があり、2.3 で解決されています。奇数リリースは実際には開発リリースであるため、これは 2.4 安定版になります。

そのため、現在の安定版ではこれを行う実際の方法はまだありません。唯一の方法は、実際に3つの条件付きクエリを実行することです.1つは行をチェックし、次にif挿入または更新します。

ここでロックに実際の問題があった場合、この機能を唯一のJSで実行できると思いますが、それは悪いことですが、この更新を単一のスレッドにロックします。

于 2012-12-31T09:02:44.517 に答える