@@ -300,3 +300,44 @@ An _id, a hash of conditions, or ``false``/``nil`` can now be included:
300300 Band.exists?(BSON::ObjectId('6320d96a3282a48cfce9e72c'))
301301 Band.exists?(false) # always false
302302 Band.exists?(nil) # always false
303+
304+
305+ Added ``:replace`` option to ``#upsert``
306+ ----------------------------------------
307+
308+ Mongoid 8.1 adds the ``:replace`` option to the ``#upsert`` method. This option
309+ is ``false`` by default.
310+
311+ In Mongoid 8 and earlier, and in Mongoid 8.1 when passing ``replace: true``
312+ (the default) the upserted document will overwrite the current document in the
313+ database if it exists. Consider the following example:
314+
315+ .. code:: ruby
316+
317+ existing = Player.create!(name: "Juan Soto", age: 23, team: "WAS")
318+
319+ player = Player.new(name: "Juan Soto", team: "SD")
320+ player.id = existing.id
321+ player.upsert # :replace defaults to true in 8.1
322+
323+ p Player.find(existing.id)
324+ # => <Player _id: 633b42f43282a45fadfaaf9d, name: "Juan Soto", age: nil, team: "SD">
325+
326+ As you can see, the value for the ``:age`` field was dropped, because the
327+ upsert replaced the entire document instead of just updating it. If we take the
328+ same example and set ``:replace`` to ``false``, however:
329+
330+ .. code:: ruby
331+
332+ player.upsert(replace: false)
333+
334+ p Player.find(existing.id)
335+ # => <Player _id: 633b42f43282a45fadfaaf9d, name: "Juan Soto", age: 23, team: "SD">
336+
337+ This time, the value for the ``:age`` field is maintained.
338+
339+ .. note::
340+
341+ The default for the ``:replace`` option will be changed to ``false`` in
342+ Mongoid 9.0, therefore it is recommended to explicitly specify this option
343+ while using ``#upsert`` in 8.1 for easier upgradability.
0 commit comments