[SERVER-5247] Support updating more than one array with the positional operator ($) Created: 08/Mar/12  Updated: 07/Mar/14  Resolved: 11/Aug/13

Status: Closed
Project: Core Server
Component/s: Querying, Write Ops
Affects Version/s: None
Fix Version/s: None

Type: Improvement Priority: Major - P3
Reporter: Ross Lawley Assignee: Unassigned
Resolution: Duplicate Votes: 2
Labels: array, matcher, positional-operator
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: File query_order.js     File query_order.py    
Issue Links:
Duplicate
duplicates SERVER-6864 positional operator projection inclus... Closed
Participants:

 Description   

Currently the positional operator only works on a single array match. If the query matches more than one array, the positional operator ($) does not differentiate between the arrays and only replaces the positional operator with a single value for all updates.

This is not the nested arrays case but simply more than one array at the same level for example.



 Comments   
Comment by Asya Kamsky [ 11/Aug/13 ]

Here's an example from googlegroups - basically if query part includes two arrays, the LAST array used and matched will determine which position in the array being updated gets matched - this gives incorrect update result:

Sample document:
{
  "Sales" : [{
      "foo" : "Pickles",
      "bar" : "Green",
      "Status" : "Pending",
      "ProposedStatus": "Closed"
    }, {
      "foo" : "Gravy",
      "bar" : ObjectId("4d51fb56330a000000000cb2"),
      "Status" : "Pending",
      "ProposedStatus": "Closed"
    }, {
      "foo" : "Ointment",
      "bar" : "Red",
      "Status" : "Pending",
      "ProposedStatus": "Closed"
    }],
  "Tags" : [{
      "Category" : "Bird",
      "Values" : ["Butterfly", "Sandwich", "Ring", "Clock"]
    }]
}
 
I want to remove the "ProposedStatus" field of the third element in the Sales array, but I need to match this document by tags.  I have tried this:
 
db.collection.update( 
    { "Sales" : { "$elemMatch" : { "foo" : "Ointment", "bar" : "Red" } }, "Tags" : { "$elemMatch" : { "Category" : "Bird", "Values" : { "$in" : ["Butterfly"] } } } }, 
    { "$unset" : { "Sales.$.ProposedStatus" : 1  } } 
);
 
...but this removes the "ProposedSatatus" field of the first element in the Sales array.  My tests indicate that if I put the Tags query before the Sales query, then the right element gets updated.
 
db.collection.update( 
    { "Tags" : { "$elemMatch" : { "Category" : "Bird", "Values" : { "$in" : ["Butterfly"] } } }, "Sales" : { "$elemMatch" : { "foo" : "Ointment", "bar" : "Red" } } }, 
    { "$unset" : { "Sales.$.ProposedStatus" : 1  } } 
);
 

I reproduced this as well - Ross' original example attached to this bug shows that it's not $elemMatch being present twice, it's any array being involved in the query (and being in position after the elemMatch/intended positional match).

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