Reputation: 8423
Let's say I want to update the whole document and override all fields, except _id. What of the three methods is the best in terms of resource consumption:
1. Set the complete document as update parameter, so all fields are passed
Example:
collection.update({_id: docId}, {$set:updateDoc});
2. Calculate a delta document between the original and the updateDoc
Example:
const originalDoc = collection.findOne(docId);
const deltaDoc = calculateDeltaFct(originalDoc, updateDoc); //get changed fields
collection.update({_id: docId}, {$set:deltaDoc});
3. Use the Mongo 3.2. replaceOne function
Example:
collection.replaceOne({_id: docId}, {$set:updateDoc});
I have an assumption of the pros and the cons of each methods but I want to be sure what to choose and why. I am not sure how to measure it precisely, so maybe someone can help.
Background:
I have a metrics collection where many documents are updated often, but the fields to be updated vary a lot, so it is hard to write an update method for each field. Instead I intend to just throw all data in and update all fields, so I keep my code clean with only one update method for all updates.
Update:
In my setup, there are no subdocuments embedded in the document structure. I also have no sharding and replication in my (dev) setup.
Furthermore I found some method (collection.explain) which I will use to research on that topic, too. Nevertheless, any help or hint is much appreciated.
Upvotes: 4
Views: 3108
Reputation: 331
I'm not sure if this is the "fastest" way, but this is one method of updating the whole document "except _id", paying special attention to the part about "fields to be updated vary a lot".
Note: this example assumes your "updateDoc" has the _id
field included in it.
I wanted to update all fields without having to actually explicitly state them.
My situation:
Attempted update of all document fields:
await examCollection.findOneAndUpdate(
{_id: new ObjectID(this.examId)},
{$set: this.data}
)
...except, this.data
happened to have _id
in it as well, which I didn't want to update. (In fact, it gave me an error, because _id
is immutable.)
So, for my workaround, I ended up "deleting" all fields on the object that I didn't want to update (i.e. _id
).
Successful update of all document fields, except specified ones:
// (1) specify fields that I don't want updated (aka get rid of them from object)
delete this.data._id
//delete this.data.anotherField
//delete this.data.anotherField2
//delete this.data.anotherField3
// (2) update MongoDB document
await examCollection.findOneAndUpdate(
{_id: new ObjectID(this.examId)},
{$set: this.data}
)
This was much easier than explicitly stating all the fields that I did want to update, because there were A LOT, and they could potentially change in the future (new fields added, fields deleted, etc.).
Hopefully this strategy can help!
Note: In reality, I did my "field specifying" earlier in another file, rather than immediately before updating like it shows in the example, but same effect.
Upvotes: 0
Reputation: 1105
It really depends if you require the old information before the update. If you are overwriting the info and even for one key - > value pair then I would use either update
or replaceOne
. The difference may be in time depending on the size of your collection (dataset). If that is of concern benchmark the difference. Personally I would lean towards replaceOne
, but that is just based on experience and the collections I deal with.
For what you have explained I don't think your second choice is either efficient or being memory savvy. It does not sound like you need such a calculation for simply updating data where there is no concern over overwriting previous information.
Upvotes: 1