modifiedCount is 1 even though the document didn't change - mongodb

I am using a simple updateOne query where I pull an ObjectId out of an array.
await this.portfolioModel.updateOne(
{
_id: portfolioId,
'watchlist.custom._id': watchlistId
},
{
$pull: {
'watchlist.custom.$.assets': assetId
}
}
)
But I want to detect if the document actually changed or if the assetIds wasn't in the array to begin with. The problem is that even though the document hasn't changed MongoDB still returns modifiedCount with 1.
{
acknowledged: true,
modifiedCount: 1,
upsertedId: null,
upsertedCount: 0,
matchedCount: 1
}
I checked the document and the __v doen't increment with the updates so I don't know why MongoDB thinks the document has changed.
This is how the document looks (before and after update):
{
"_id": {
"$oid": "600188dab0b1c70050084e3e"
},
"watchlist": {
"all": [],
"custom": [
{
"assets": [],
"_id": {
"$oid": "624d7a18c89b3937212b3a55"
}
}
]
},
"__v": 18,
"createdAt": {
"$date": "2021-05-11T22:19:05.450Z"
},
"updatedAt": {
"$date": "2022-04-06T11:45:37.415Z"
}
}

I encountered this same issue using mongoose 6.3.5 and MongoDB serverless version 5.3.1.
The fix for me was removing {timestamps: true} from my schema. This causes the document to be 'modified' even if no change was made to its values. I believe it is because the 'updatedAt' value would change whenever updateOne() would access the document.

Related

Update & Remove child document (subdocument) using nestjs and mongoose

I have recently started using nestjs with mongoose. I have an existing app in nodejs and mongoose. I am not able to figure out how to update and remove a subdocument based on the document _id and subdocument _id. I am trying to update & remove productSubCategory array elements
Below is the sample document
{
"_id": "62d389321d26d175d140425e",
"productCategory": "snacks",
"active": true,
"productSubCategory": [
{
"productSubCategory": "biscuits",
"active": true,
"productSecondSubCategory": [],
"created_at": "2022-07-17T16:46:13.000Z",
"updated_at": "2022-07-17T16:46:13.000Z",
"_id": "62d43cd5ff45a56ae27de6d0"
}
],
"created_at": "2022-07-17T03:59:46.416Z",
"updated_at": "2022-07-17T03:59:46.416Z",
"__v": 1
},
You could use the findByIdAndUpdate function:
Document.findByIdAndUpdate(document_id, { $pull: { 'productSubCategory._id': subdocument_id } })

Update query in mongodb

Suppose I have this document in mongodb collection:
{
"_id": {
"playerId": "113069",
"tournamentId": "197831"
},
"__v": 0,
"playerName": "David WArner",
"pointsTotal": 426
}
I update it using this update query(using mongoose):
await PointsTotal.findOneAndUpdate(
{
_id: {
playerId: player._id,
tournamentId: tournamentId,
}
},
{
$set: {
playerName: playerName,
pointsTotal: totalPoints
},
},
{
upsert: true,
}
);
}
But, if the playerName and totalPoints is same as before updating, will it perform update operation to overwrite these fields and I am able to listen this update in change stream or not?
No, if there is no change to the document MongoDB will not perform a write, there will be no operation in the oplog, and nothing will appear in the change stream.

Updating a nested Array in using UpdateOne()

I'm having an issue updating a nested Array in a document. Reading around the topic i've come across various method, one that i've tweaked below, however nothing seems to work for me!
I'm trying to update the field systemUpdate_DT which is in a parent Array called List and a child array called customData. I'm referring to the object in the child array using the key _id of the parent array and key field_id in the child array.
How do I update the systemUpdate_DT of the respective object?
Live Example: https://mongoplayground.net/p/453OFPOQqBp
A document in the collection looks like:
[
{
"_id": "6032a5ad80443334a35f2232",
"List": [
{
"_id": "6032a5af80443334a35f2234",
"customData": [
{
"_id": "6032a5bc80443334a35f223c",
"systemUpdate_DT": null,
"field_id": "6032a5bc80443334a35f223b"
},
{
"_id": "6032a5c280443334a35f223e",
"systemUpdate_DT": null,
"field_id": "6032a5c280443334a35f223d"
}
]
},
{
"_id": "6032a5b080443334a35f2236",
"customData": [
{
"_id": "6032a5bc80443334a35f223c",
"systemUpdate_DT": null,
"field_id": "6032a5bc80443334a35f223b"
},
{
"_id": "6032a5c280443334a35f223e",
"systemUpdate_DT": null,
"field_id": "6032a5c280443334a35f223d"
}
]
}
]
}
]
My Update Query looks like:
db.collection.updateOne({
{
"List._id": mongodb.ObjectId("6032a5af80443334a35f2234"),
"List.customData.field_id": mongodb.ObjectId("6032a5bc80443334a35f223b")
},
{
$set: {
"List.$.customData.systemUpdate_DT": 'updatedDTTM'
}
})
As there's two nested arrays in your document, you can't set the field with classic positional operator '$'.
Instead, you should use the arrayFilters option like this:
db.collection.update({
"_id": ObjectId("6032a5ad80443334a35f2232")
},
{
$set: {
"List.$[list].customData.$[customData].systemUpdate_DT": "updatedDTTM"
}
},
{
"multi": false,
"upsert": false,
arrayFilters: [
{
"list._id": {
"$eq": ObjectId("6032a5af80443334a35f2234")
}
},
{
"customData._id": {
"$eq": ObjectId("6032a5bc80443334a35f223c")
}
}
]
})
try it online: mongoplayground.net/p/fb_86rNUKvt

Move data from inside nested array

I have inserted multiple documents in my Mongo database incorrectly. I have accidentally nested the data inside another data object:
{
"_id": "5cdfda8ddc5cf00031fd3949",
"payload": {
"timestamp": "2019-05-18T10:12:29.896Z",
"data": {
"data": {
"name": 10,
"age": 10,
}
}
},
"__v": 0
}
I would like the document to not have the extra data object. So I would like it to look like this:
{
"_id": "5cdfda8ddc5cf00031fd3949",
"payload": {
"timestamp": "2019-05-18T10:12:29.896Z",
"data": {
"name": 10,
"age": 10,
}
},
"__v": 0
}
Is there a way in Mongo for me to update all the documents that have 2 data objects to just have one like shown above?
Alas, you cannot do this with one database request. You have to loop over all documents programmatically, set the new data and update them in the database.
You could use the aggregation framework, which won't let you update in place, but you could use the $out operator to write the results to a new collection, if that's an option.
db.collection.aggregate([
{
$project: {
__v : 1,
"payload.timestamp" : 1,
"payload.data" : "$payload.data.data"
},
},
{
"$out": "newCollection"
}
])
Or if you have a mixture of docs with correct format and docs with incorrect format, you can use the $cond operator to determine the correct output:
db.collection.aggregate([
{
$project: {
__v : 1,
"payload.timestamp" : 1,
"payload.data" : {
$cond: [
{ $ne : [ "$payload.data.data", undefined]},
"$payload.data.data",
"$payload.data"
]}
}
},
{
"$out": "newCollection"
}
])

How to update multi property value of an object in array in MongoDB?

The following is my database schema update operation:
db.school_student.update({ _id: "003" }, {
$set: {
"result": [
{
"_id": "001",
"isPassed": false
},
{
"_id": "002",
"isPassed": false,
},
{
"_id": "003",
"isPassed": false
}
]
}
});
I want to change ALL the property values of "isPassed" to true. Is there any way to update this? I have been struggling with this the whole day :(
db.school_student.update({},{$Set :{"result.isPassed" : true}}
this should update all the documents in school_student collection and set isPassed to true.