[SERVER-54687] `$pull`ed index should not override query-matched index for `$(update)` Created: 21/Feb/21  Updated: 04/Mar/21  Resolved: 03/Mar/21

Status: Closed
Project: Core Server
Component/s: Querying
Affects Version/s: 4.2.12
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: TimTIM Wong Assignee: Edwin Zhou
Resolution: Duplicate Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: PNG File Screenshot 2021-02-21 232554.png    
Issue Links:
Duplicate
duplicates SERVER-18500 Resolve ambiguity of positional proje... Backlog
Related
related to DOCS-14267 Clarify ambiguous $ positional operat... Closed
Operating System: ALL
Steps To Reproduce:

Run the following in a collection `testCol`.

db.testCol.insertOne({
 _id: "TEST",
 toPull: ["A", "B", "C", "D", "E"],
 toSet: [
  {id: "E"},
  {id: "D"},
  {id: "C"},
  {id: "B"},
  {id: "A"},
 ]
});

db.testCol.updateOne({
 _id: "TEST",
 toPull: "B",
 toSet: {$elemMatch: {id: "B"}}
}, {
 $set: { "toSet.$.data": "Z" },
 $pull: { toPull: "B" },
});

db.testCol.findOne({_id: "TEST"});

Participants:

 Description   

The index of `$pull`ed element in an unrelated field becomes `$(update)` when `$set`ting another field. See steps to reproduce. Expected result is to set `{data: "Z"}` on the forth element, but it actually set it on the second element, due to pulling the second element of another unrelated field.



 Comments   
Comment by Edwin Zhou [ 04/Mar/21 ]

Hi wegylexy@gmail.com,

We agree and think that this behavior can be further clarified in our documentation. I've opened up DOCS-14267 to track this work.

Thanks,
Edwin

Comment by TimTIM Wong [ 03/Mar/21 ]

May want to clarify this in the documentation that `$` will be affected by other array operations even though `$` is not explicitly involved in those operations.

Comment by Edwin Zhou [ 03/Mar/21 ]

Hi wegylexy@gmail.com,

Thank you for your report. We agree that this can be unhelpful and confusing behavior and we believe this issue duplicates SERVER-18500, which describes that multiple array matches can lead to ambiguous positional operator projections.

You may find the $[<identifier>] operator helpful, where updating an element in an array can be made more explicit.

db.test_col.updateOne(
  {
    _id: "TEST",
  },
  {
    $set: { "toSet.$[element].data": "Z" },
    $pull: { toPull: "B" },
  },
  {arrayFilters: [{element: {id: "B"}}]}
);

will output

{
  _id: "TEST",
  toPull: ["A", "C", "D", "E"],
  toSet: [
    { id: "E" },
    { id: "D" },
    { id: "C" },
    { id: "B", data: "Z" },
    { id: "A" },
  ],
};

Hope this helps!

Best,
Edwin

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