[SERVER-53895] updateOne and pull cannot remove content other than the first element Created: 20/Jan/21  Updated: 27/Oct/23  Resolved: 20/Jan/21

Status: Closed
Project: Core Server
Component/s: Usability
Affects Version/s: 4.4.3
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: qingzhi li Assignee: Edwin Zhou
Resolution: Works as Designed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Operating System: ALL
Steps To Reproduce:

 

// mongo mongodb://localhost:27018/test
// Drop table, Clean up the environment
db.test_scores.drop()
 
// Insert test data
db.test_scores.insertMany(
    [
        {
            _id: 1, scores: [
                {_id: 1},
                {_id: 2},
                {_id: 3},
            ]
        },
        {
            _id: 2, scores: [
                {_id: 4},
                {_id: 5},
                {_id: 6},
            ]
        }
    ]
    )
 
// Check data
// [
//   {
//     "_id": 2,
//     "scores": [
//       {
//         "_id": 4
//       },
//       {
//         "_id": 5
//       },
//       {
//         "_id": 6
//       }
//     ]
//   }
// ]
db.test_scores.findOne({_id: 2})
 
// Perform updateOne operation on the second piece of data
db.test_scores.updateOne(
    {},
    {$pull: {scores: {_id: 5}}}
    )
 
// Check data, scores._id:5 still in there
// [
//   {
//     "_id": 2,
//     "scores": [
//       {
//         "_id": 4
//       },
//       {
//         "_id": 5
//       },
//       {
//         "_id": 6
//       }
//     ]
//   }
// ]
db.test_scores.findOne({_id: 2})
 
// Check data
// [
//   {
//     "_id": 1,
//     "scores": [
//       {
//         "_id": 1
//       },
//       {
//         "_id": 2
//       },
//       {
//         "_id": 3
//       }
//     ]
//   }
// ]
db.test_scores.findOne({_id: 1})
 
// Perform updateOne operation on the first piece of data
db.test_scores.updateOne(
    {},
    {$pull: {scores: {_id: 3}}}
    )
 
// Check data, scores._id:3 is gone
// [
//   {
//     "_id": 1,
//     "scores": [
//       {
//         "_id": 1
//       },
//       {
//         "_id": 2
//       }
//     ]
//   }
// ]
db.test_scores.findOne({_id: 1})

 

Participants:

 Description   

I am a normal user of mongo. When I use mongoDB to perform a combination of updateOne and pull, its behavior does not meet my expectations. I am not sure if it is a bug or the result of following established rules.

The official document's description of updateOne is that it will update a single document, but in my test statement, if the selector can hit multiple records, mongo will only check whether the first record meets the requirements, and if it does not meet the requirements, it will not check the following Record whether the requirements are met.

 

As shown in the steps to reproduce, my question is why do the same operations on id 1 and 2 return different results?

From what I have observed, the explanation I can give is because id 1 is in the first position, and updateOne will only check this one. Is this correct?



 Comments   
Comment by qingzhi li [ 21/Jan/21 ]

Thank you for your reply. Now I know it.

Comment by Edwin Zhou [ 20/Jan/21 ]

Hi moqimoqidea@gmail.com,

db.collection.updateOne() will select and modify only one document. A small correction in your guess:

My guess is that because the selector is empty, the pull operation will only look for the first record

The pull operation doesn't query for documents, but rather it will update the documents that have been queried. Since updateOne({}) updates only one document and the query is empty, it selects only

{
  _id: 1,
  scores: [{ _id: 1 }, { _id: 2 }, { _id: 3 }],
}

and tries to pull { _id: 5 } from scores. Since scores does not contain an element with { _id: 5 }, nothing will change.

You can update multiple documents using db.collection.update() with { multi: true }

db.collection.update({}, { $pull: { scores: { _id: 5 } } }, { multi: true })

which will pull { _id: 5 } from all documents with the field scores containing { _id: 5 }.

Best,
Edwin

Comment by qingzhi li [ 20/Jan/21 ]

My guess is that because the selector is empty, the pull operation will only look for the first record, so this is a feature and not a bug.

If this is the case, please close this one jira, thank you.

Generated at Thu Feb 08 05:32:08 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.