MongoDB の update は部分 update ではない

まとめ

  • MongoDB の update はレコードのID以外の要素を全て置き換える
  • 指定したカラムだけ置き換えてはくれない
  • 部分 update したい場合は専用の方法でクエリを作る

MongoDB の update はレコードをほぼ全て置き換える

以下のように insert して update を実行します

db.test.insert({a: 1})
db.test.update({a:1}, {b: 1})
# ruby版
mongo = Mongo::Client.new("mongodb://localhost")
col = mongo[:test]
col.insert_one({ a: 1 })
col.find(a: 1).replace_one({b:1})

insert と update とでキーが違うため、指定した部分だけが書き換わり
{a:1, b:1}
となりそうですが、実際は
{b:1}
と、後のデータで完全上書きされてしまいます。

このように、MongoDB の update はデータの全置き換えを実行します。
なお、ObjectId は変わらないため、消して再度 insert しているのではなく、ObjectId 以外のデータを全て変更しています。

回避方法

もちろん毎度上書きだととても不便なため、回避方法が存在します。

以下のように、update する際に $set のキーとして変更するデータのみを渡します。
これにより、指定したものだけ書き換えられるようになります。

db.test.update({a:1}, {$set:{b: 1}})
# ruby版
col.insert_one({ a: 1 })
col.find(a: 1).replace_one('$set' => {b:1})