Does MongoDB still update or overwrite a document if the values will be unchanged?

Hi,

I’ve gotten into a discussion about what to expect from MongoDB when doing updates. I’m working with Mongoose and the phenomena happens for both update and updateMany.

It seems, if the update object just happens to be the same as the document to be updated, then MongoDB doesn’t count it as modified (nModified).

My question is, does MongoDB still update or overwrite the document, despite the values being the same and then after the update, considers the update a “non-modification”, because the value in the document is still the same?

Or, does MongoDB not carry out the modification, if it notices the values in the document and the update are the same?

Scott

Yes @scott_molinari, In mongoDB if we update the records using updateMany clause it will not update the record as the new record is same so the count of modified if ZERO. but when we use only update clause it will update the record. Here are the screenshots of update and updateMany clauses:

Update Many Clause Screen Shot

image

Update Clause Screen Shot
image

I hope this will help you in understanding the update concept.

Hey. Thanks for answering @Nabeel_Raza. But, I’m still not really clear on what MongoDB is “thinking” internally.

For updateMany and/ or update, if the data to update is the same as the data in the document, does MongoDB still carry out the update (overwriting the same data), and then notices the data is the same and returns “nModified: 0”, or does MongoDB see the data is the same and does not modify the document at all?

Scott

To expand on the issue. Mongoose has a pre hook available to add timestamps. And, it correctly timestamps basically any update with an UpdatedAt timestamp. However, if MongoDB doesn’t overwrite the document as mentioned above, then the timestamping would be incorrect. If, however, MongoDB does overwrite the document, but just doesn’t count it as modified due to the data being the same, then the timestamping would be correct, just not totally logical.

I was also trying to explain that for the update or updateMany to be truthful/ consistent, a proper filter would need to be used. My debators are saying “no”, that can’t be right and I should prove it, so they can believe me and thus why I’m here asking.

Maybe @Asya_Kamsky can chime in? Hi Asya. Very long time no see. :slight_smile:

Scott

for updateMany it check the data is the data is same or not? if same then don’t replace if not same then update the data. where as in update only single record is updated.

Yes @scott_molinari, when we use the date timestamp field for updation then it will update the field with new record(as the records is same) but will update the timestamp field.

/* 1 */
{
“_id” : ObjectId(“5f72bec821f28d445c34c38c”),
“name” : “Jeff”,
“roll#” : “R101”,
“date” : ISODate(“2020-09-29T04:57:44.398Z”)
}

/* 2 */
{
“_id” : ObjectId(“5f72becf21f28d445c34c38d”),
“name” : “Ben”,
“roll#” : “R102”,
“date” : ISODate(“2020-09-29T04:59:45.213Z”)
}

/* 3 */
{
“_id” : ObjectId(“5f72bf3121f28d445c34c38e”),
“name” : “Ben”,
“roll#” : “R102”,
“date” : ISODate(“2020-09-29T04:59:45.213Z”)
}

/* 4 */
{
“_id” : ObjectId(“5f72bf3221f28d445c34c38f”),
“name” : “Ben”,
“roll#” : “R102”,
“date” : ISODate(“2020-09-29T04:59:45.213Z”)
}

/* 5 */
{
“_id” : ObjectId(“5f72bf3221f28d445c34c390”),
“name” : “Ben”,
“roll#” : “R102”,
“date” : ISODate(“2020-09-29T04:59:45.213Z”)
}

this is my sample data in a collection. Let’s use updateMany clause to update the document:
image
here ^ is the result that when we update the document using timestamp field the modified count was changed as timestamp is always changing.

And if you comment out the date field then the count will be zero. as the rest of the data is same. When so ever the timestamp field is in document then the update count will be changed.
In backend the data is not updated as the new data is also the same as previous so no need to change it.
I hope you will get what you need.

@Nabeel_Raza - Are you a MongoDB developer?

Scott

Yes :wink:

Regards: Nabeel

Ok. Fantastic. I’m now understanding the whole situation.

So, my last question to you @Nabeel_Raza (and thanks so much for your help):

The way to make sure the pre hook updatedAt functionality with updateMany can work properly is only when the query properly filters for the data that has to be updated. Trying to use the internal “if the data is the same, don’t update it” logic isn’t going to be enough. You need to filter to have updates work on the data as you wish it to to get the right updateAt timestamping. Would you also agree to that?

Or put another way. There is no way for Mongoose (or any other client) to know what documents were modified and which weren’t modified during an updateMany operation, when the update data is the same as in some documents, thus some of them not getting modified. Only a count of modified docs is returned, which is useless for the determination of “hooking in” an updatedAt timestamp on only those records that were modified.

Sorry. And just to double check, as a MongoDB developer, you work within the source code of MongoDB and know its inner workings? Sorry, for acting so mistrustful. It’s not my intention. :blush:

Scott

@scott_molinari, i think you misunderstand me. I am not the part of MongoDB Developer Community, I am just using MongoDB for a project & have little bit experience on it.
If you are updating the data & that’s the same data as previous then it doesn’t matter but if you are using the timestamp field with updation then it will update the timestamp field rest will be the same as the timestamp always changes. When so ever you use the timestamp field it will update the records see example
The roll# was the same but the date isn’t so it update the record with count 4 as modified count.

Ah. Ok.

Yeah, so then we are back to the core question. Since the timestamp pre hook on updateMany isn’t reacting to properly “ignored” updates, it is timestamping incorrectly, thus, is it true when I say, the only way to make sure an updateMany works with timestamping, is to properly filter on the data that should be updated. If you see in the example I gave above, the user is not filtering for anything, yet expecting only two of the docs to get timestamped, because MongoDB is not updating the last doc and correctly sending back nModified as 2.

No filter, no proper timestamps with the pre hook and don’t expect Mongoose to do it right, because it will never know that an update of a doc didn’t occur. That is the simple answer or rather the frame of mind one should have to the situation to understand how to make the timestamping work right.

Or put another way, you have to make sure you don’t “hit” docs that MongoDB would not update, because the data is already “correct” and no modification is necessary.

Scott

Yes @scott_molinari, this is same as we discuss earlier. if we update the document and new document is same as previous then the modification flag will be 0. But if we use some timestamp field in it then only that field will be updated, rest will be same.
This doesn’t mean that we have incorrect data as the new record was same as previous so it doesn’t matter, basically new record is same as previous. So saying that the data is not in updated version it is wrong, it’s the updated document.
@Nabeel_Raza

1 Like

Got it. Thing is, the person I was debating this with is saying that the timestamping shouldn’t happen with his non-filtered example. His logic is flawed, because MongoDB doesn’t offer the right time to “hook” into the system for the timestamping. Theoretically, it should be within the database, not the client, when timestamping occurs, and AFAIK, Mongo offers no such facility.

So, filter on what should be updated or expect funky results with the updatedAt timestamping, is the clear answer for me.

Scott

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.