26

I have read this related question, but the one below is different. The mongodb c# driver has a ReplaceOne method (& an async counterpart) on the document collection class, which can be used to replace the entire contents of a document that fits the filter argument. The alternative is to use the UpdateOne or UpdateMany methods (or async counterparts), which requires the building of an UpdateDefinition<TDocument>.

My question has to do with the implications of choosing one of these methods over the other (replace vs update), in cases where you have enough input data to choose either to achieve the same result. In other words, if I have the entire original document and only wish to update a small slice of its contents.

The first factor I can think of is the payload sent to the database server. Though I have not read any mongodb c# driver source and could not find any documents to verify this, it seems that ReplaceOne could have to send more bytes over with the update operation, especially for larger documents. The Update... methods seem like they could get away with a smaller payload by only sending over update metadata for the slices of the document that require modification (in addition to filter criteria, which both methods must send). Can anyone verify if this is an accurate assumption?

Another factor brought up by a colleague is that the choice of the method (update vs. replace) could affect document indexing as well. The assumption here is that using ReplaceOne has the potential to cause the database to rebuild all indexes for the document being updated, whereas the Update... methods have enough change metadata information to avoid rebuilding indexes on fields which are not part of the metadata in the update definition. Can anyone verify whether or not mongodb internally handles document index building differently depending on whether a document is modified using replace versus update?

A third factor came up for us a couple of times already, regarding the AddToSet and PullFilter methods on the Update<TDefinition> class. It seems that the Update... methods will not allow you to modify a set in a document (like a json array) by both adding items to it and removing items from it at the same time; these operations have to be sent individually, using 2 separate calls to the Update... method along with separate Update<TDefinition> instances (though with the same filter arguments). The ReplaceOne method, in this case, seems to be the only way to make this kind of document change in a single "transaction", at least when using the C# driver. We're currently using Update... over ReplaceOne for now because we're uncertain whether the alternative would negatively affect indexing as mentioned above.

Other than these, what are any additional implications that could lead one to choose from the ReplaceOne family of methods over the Update... family or vice-versa? Again, this is assuming that you have enough input data (i.e. all document data) to achieve the same result with either approach, don't mind mutating state directly (via replace), and don't mind building mongo definitions (via update).

danludwig
  • 45,241
  • 21
  • 150
  • 230
  • To briefly sum up, there actually is "no such method" as `ReplaceOne`. This is only an "API Wrapper" around the basic "update" operation, done with a "constraint" that you cannot specify "update operators" ( `$set`, `$addToSet`, `$pull` etc ) in the block. This is actually not a "server method" but only an API implementation. A regular "update" without any modifiers "replaces" by default. Replacing means "replacing". So if you really don't need to "replace" the whole thing, then use the atomic modifiers, which only update the properties specified and nothing else. – Neil Lunn Sep 06 '17 at 02:32
  • @NeilLunn thank you, this helps, and I think it at least answers the question about indexing. However, does the update payload sent to the db server have potential to be larger with a replace for more minor updates to larger documents? If you need to `addToSet` and `pull` from the same set in a single update, is this a good case for using `ReplaceOne` since the update API can't achieve this? – danludwig Sep 06 '17 at 14:43

2 Answers2

3

Since mongo data is unstructured the main advantage of the replaceOne vs Update is that is guaranteed you will have all your fields deleted and replaced with the new document, making the query simpler on your part

1) True, but the least of your problems, the search criteria will be the same in both, but replaceOne will require the entire document to be passed in the query, still worth when you have the full new Doc and want be sure it will end that way

2 ) reindex on replace -> yes, replaceOne replace the entire documment instead of updating an existing one, if you update on element that is on the index, the index will need to readjust to the change, but with replace it will always need to readjust. the _id index is not affect by both operations ( i think )

3) If you already have the value you want to be, you wouldn't need to replace the full document to change a single field, making it be re indexed by all fields, you should use $set operation for that, which you could think as a ReplaceOne for a single field instead of the entire document

https://docs.mongodb.com/manual/reference/method/db.collection.replaceOne/index.html https://docs.mongodb.com/manual/reference/operator/update/set/

zero
  • 162
  • 1
  • 5
2

If incorporated in a REST service, the replaceOne method would align well with a PUT operation, where you would send an entire object in your request body along with an object identifier, and this could then be persisted in the database in its entirety. The distinguishing characteristic of a PUT operation being that it is idempotent (you can run it repeatedly). replaceOne takes an upsert option which defaults to false, but if this were set to true (and the search criteria was on a uniquely indexed field) it would make the operation repeatable regardless of whether the document was independently removed.

The update operation is more akin to a POST operation, since it just updates part of a document rather than replacing it entirely. It also takes an upsert option, but if the document was removed by another process then the resulting document could be malformed and the update might fail.

robjwilkins
  • 4,444
  • 3
  • 38
  • 51
  • 5
    Agreed on replace being akin to an http put, but i would argue that update is more akin to an http patch -- but you are right, if you can't patch, then it would be a post. – danludwig Sep 15 '17 at 18:55