Another Question in the Practice Test is incorrect

I came across another question in the Practice Test that is incorrect. The question goes as follows:

The options provided are as follows:


From my understanding, all the 5 options provided are incorrect. This is because _id field is immutable, so a db.employees.replaceOne() can’t be used to replace /update the _id field value from 1 to 10.

However, following is what you have provided as the correct answer with it’s justification.

Hey @PuneetC

You are correct that the _id is immutable, which means we will not be able to change it with a update() command. However replaceOne replaces the entire document with a new document. Therefore the _id is not changed.

SEE BELOW for complete explanation. :smile:

And if a document with _id : 10 existed the operation would had fail because _id must be unique across a collection.

@natac13

So, are you trying to say that the question is correct? and that update() on _id fails but replaceOne() on _id will not fail ?

It will fail in case of replaceOne() as well. See the o/p below:

db.test_replaceone.insertMany([
… {
… _id: 1,
… name: “Joe”,
… last: “Doe”
… },
… {
… _id: 2,
… name: “Jane”,
… last: “Doe”
… },
… {
… _id: 3,
… name: “Jeff”,
… last: “Doe”
… }
… ])
{ “acknowledged” : true, “insertedIds” : [ 1, 2, 3 ] }

Now if we run the replaceOne(), it will throw this error :slight_smile:

db.employees.replaceOne(
… { “last”: “Doe” },
… { “_id”: 10, “name”: { “first”: “Walter”, “last”: “Doe” } }
… )
2019-07-30T16:23:23.845+0530 E QUERY [js] WriteError: After applying the update, the (immutable) field ‘_id’ was found to have been altered to _id: 10.0 :
WriteError({
“index” : 0,
“code” : 66,
“errmsg” : “After applying the update, the (immutable) field ‘_id’ was found to have been altered to _id: 10.0”,
“op” : {
“q” : {
“last” : “Doe”
},
“u” : {
“_id” : 10,
“name” : {
“first” : “Walter”,
“last” : “Doe”
}
},
“multi” : false,
“upsert” : false
}
})
WriteError@src/mongo/shell/bulk_api.js:461:48
Bulk/mergeBatchResults@src/mongo/shell/bulk_api.js:841:49
Bulk/executeBatch@src/mongo/shell/bulk_api.js:906:13
Bulk/this.execute@src/mongo/shell/bulk_api.js:1150:21
DBCollection.prototype.replaceOne@src/mongo/shell/crud_api.js:489:17
@(shell):1:1

1 Like

@steevej-1495

Well, it will fail even if you try to update the _id to a value that doesn’t exist in the collection. Simply said, you can’t update the _id field (irrespective of the new value being present in the collection or not)

Any operation whether update(), updateOne(), updateMany(), replaceOne(), or findAndModify() that tries to change the value of _id will fail.

1 Like

@ MongoDB University team,

Would appreciate if you could get somebody from your team to look into this and confirm if the question is correct / incorrect ?

1 Like

Hey @PuneetC

You are absolutely right! :+1: I just tried out what you had and I get the same error as you. My apologies for the original mistake. replaceOne or replace does not change the _id field.

Glad you saw this and I am looking forward to the response about the practice exam.

Hi @PuneetC, @natac13, @steevej-1495,

You are right! The question and the correct option is wrong. But let me try to see what might our instructor have been tried to ask in the question.

So, I created the same collection test_replaceone and inserted three documents:

test > db.test_replaceone.find()

{ "_id" : 1, "name" : "Joe", "last" : "Doe" }

{ "_id" : 2, "name" : "Jane", "last" : "Doe" }

{ "_id" : 3, "name" : "Jeff", "last" : "Doe" }   

First Scenario: without _id field:

If we run below command:

test > db.test_replaceone.replaceOne( { "last": "Doe" }, {  "name": { "first": "Walter", "last": "Doe" } } )
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

Then:

test > db.test_replaceone.find()
{ "_id" : 1, "name" : { "first" : "Walter", "last" : "Doe" } }
{ "_id" : 2, "name" : "Jane", "last" : "Doe" }
{ "_id" : 3, "name" : "Jeff", "last" : "Doe" }

This explains that the first document returned by query filter: {last: Doe} will be replaced.

Second Scenario: with _id field matching second most document i.e if we try replacing document with _id: 3

Current documents:
test > db.test_replaceone.find()
{ "_id" : 1, "name" : { "first" : "Walter", "last" : "Doe" } }
{ "_id" : 2, "name" : "Jane", "last" : "Doe" }
{ "_id" : 3, "name" : "Jeff", "last" : "Doe" }

Now, if we run below command:

test > db.test_replaceone.replaceOne( { "last": "Doe" }, { "_id": 3, "name": { "first": "Walter", "last": "Doe" } } )
2019-07-31T01:12:56.474+0530 E QUERY    [js] WriteError: After applying the update, the (immutable) field '_id' was found to have been altered to _id: 3.0 :
WriteError({
	"index" : 0,
	"code" : 66,
	"errmsg" : "After applying the update, the (immutable) field '_id' was found to have been altered to _id: 3.0",
	"op" : {
		"q" : {
			"last" : "Doe"
		},
		"u" : {
			"_id" : 3,
			"name" : {
				"first" : "Walter",
				"last" : "Doe"
			}
		},
		"multi" : false,
		"upsert" : false
	}
})
WriteError@src/mongo/shell/bulk_api.js:461:48
Bulk/mergeBatchResults@src/mongo/shell/bulk_api.js:841:49
Bulk/executeBatch@src/mongo/shell/bulk_api.js:906:13
Bulk/this.execute@src/mongo/shell/bulk_api.js:1150:21
DBCollection.prototype.replaceOne@src/mongo/shell/crud_api.js:489:17
@(shell):1:1

Because the first document returned by query filter: { "last": "Doe" } is { "_id" : 2, "name" : "Jane", "last" : "Doe" } which has _id: 2 which does not match the one mentioned in the second parameter in the replaceOne command ( _id: 3 ). So, it throws an error.

Third Scenario: with _id field matching first document i.e if we try replacing document with _id: 2

Current documents:
test > db.test_replaceone.find()
{ "_id" : 1, "name" : { "first" : "Walter", "last" : "Doe" } }
{ "_id" : 2, "name" : "Jane", "last" : "Doe" }
{ "_id" : 3, "name" : "Jeff", "last" : "Doe" }

Now, if we run below command:

test > db.test_replaceone.replaceOne( { "last": "Doe" }, { "_id": 2, "name": { "first": "Walter", "last": "Doe" } } )
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

The reason is same as first scenario: first document returned from query filter will be replaced. And as it matches _id field as well, it won’t return any error.

Final Documents:
test > db.test_replaceone.find()
{ "_id" : 1, "name" : { "first" : "Walter", "last" : "Doe" } }
{ "_id" : 2, "name" : { "first" : "Walter", "last" : "Doe" } }
{ "_id" : 3, "name" : "Jeff", "last" : "Doe" }

I hope I am able to clarify the meaning of the question. Also, I will make sure this gets updated in the Practice exam as well.


Yes, you are right. It will not change the _id field. But if we are mentioning it and it matches with the first document returned, it will replace the document otherwise not.


Thank you all again so much for debugging this and bringing it into our eyes. :slight_smile:

Kanika

1 Like

@Kanika

Your welcome!! I hope you are taking this forward with the appropriate team to get the question corrected.

Meanwhile, I have concerns about another Practice test question. Please see if you can get this addressed too. Here is the link…

Thank you!