Mongodb update Operation Updates Two-Dimensional Arrays Interesting Phenomenon

  mongodb, question

Problem description

The following data are available:

{ "_id" : 1, "name" : "dave123", "favorites" : [ "chocolate", "cake", "butter", "apples" ] }
 { "_id" : 2, "name" : "li", "favorites" : [ "apples", "pudding", "pie", "cake" ] }
 { "_id" : 3, "name" : "ahn", "favorites" : [ "pears", "pecans", "chocolate", "cherries" ] }
 { "_id" : 4, "name" : "ty", "favorites" : [ "ice cream" ] }

Then I made a mistake just now. I originally wanted to add an element to the array. As a result, I added an array to the array.

db.test.update({_id:2},{$push:{favorites:['cake']}})

The data after execution are as follows:

{ "_id" : 1, "name" : "dave123", "favorites" : [ "chocolate", "cake", "butter", "apples" ] }
 { "_id" : 2, "name" : "li", "favorites" : [ "apples", "pudding", "pie", "cake", [ "cake" ] ] }
 { "_id" : 3, "name" : "ahn", "favorites" : [ "pears", "pecans", "chocolate", "cherries" ] }

You can see that the favorites field of id2′ s document contains another array.

Try to delete this array

I know that the $pull command can delete an element in an array, but it requires a condition, so the problem is how to query another array in the array.

The order is as follows:

db.tester.find({favorites:{$in:[['cake']]}})

Output:

{ "_id" : 2, "name" : "li", "favorites" : [ "apples", "pudding", "pie", "cake", [ "cake" ] ] }

Then I tried to use update to complete this operation, because there is only one special piece of data in the collection, I did not specify a condition:

db.tester.update({},{$pull:{favorites:{$in:[['cake']]}}})

Output:

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })

I’m glad to hear that I have matched something but haven’t updated it.

Continue tossing and turning

With my efforts, I tried out such an order:

db.tester.update({favorites:{$in:[['cake']]}},{$pull:{favorites:{$in:[['cake']]}}})

Output:

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

This time the elements in this array have been deleted correctly.

The final question

WHY?

Is there any potential relationship between the query in the udpate operation and the following modification operation, or is it related to the condition in $pull?

Answer

As I guessed, it was a matter of detail.

By default, the update() method updates a single document.

By default, update will only modify the first matching data.

In the statement I used:

db.tester.update({},{$pull:{favorites:{$in:[['cake']]}}})

This command will match multiple pieces of data, since the above-mentioned rule MongoDB matches multiple pieces of data, only the first one is actually handed over to the $pull operation:

{ "_id" : 1, "name" : "dave123", "favorites" : [ "chocolate", "cake", "butter", "apples" ] }

This is the above article, but the $pull condition has not been established, so no update will be made.

This also explains why the following operations are feasible:

db.test.update({favorites:{$in:[['cake']]}},{$pull:{favorites:{$in:[['cake']]}}})

The query will only match the first piece of data, which will be processed by $pull.

How to solve the problem

It is very simple to turn on multiple modification supports in this case. The command is as follows:

db.tester.update({},{$pull:{favorites:{$in:[['cake']]}}},{multi:true})

In this way, the four pieces of data will be updated later and $pull will be matched to the corresponding content.

How did I find the problem

Observe our first two data:

{ "_id" : 1, "name" : "dave123", "favorites" : [ "chocolate", "cake", "butter", "apples" ] }
 { "_id" : 2, "name" : "li", "favorites" : [ "apples", "pudding", "pie", "cake" ] }

I tried to delete both arrayscakeElement:

db.test.update({},{$pull:{favorites:{$in:['cake']}}})

However, only the first data will be deleted, and the second data will be matched but not deleted.