[SERVER-33442] Problems using the $[<identifier] operator in 3.6.2 Created: 22/Feb/18  Updated: 16/Aug/18  Resolved: 23/Mar/18

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

Type: Bug Priority: Major - P3
Reporter: Morten L Assignee: Kelsey Schubert
Resolution: Cannot Reproduce Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Operating System: ALL
Participants:

 Description   

Hello,

I'm having major problems getting the new $[<identifier] operator to work as expected in mongodb v. 3.6.2.

I have a collection containing the following type of documents:

{
   ...,
   "documents": [
      {
         "id": "1234",
         "status": "UNTOUCHED"
      },
      ...
   ]
}

I'm executing the following update stmt:

db.mycollection.update(
   { },
   { $set: { "documents.$[e].status" : "TOUCHED" } },
   { arrayFilters: [ { "e.id": "1234" } ] }
)

And I get the following result:

code: 16837
msg: cannot use the part (documents of documents.$[e].status) to traverse the element...

I thought it might be my mongodb installation which was somehow corrupted so I did the following to verify that this was not the issue:

1) Went to Mongo Atlas and create a whole new cluster with version 3.6.2 of mongodb.

2) Create a collection, "students2", containing the following two documents:

{
   "_id" : 1,
   "grades" : [
      { "grade" : 80, "mean" : 75, "std" : 6 },
      { "grade" : 85, "mean" : 90, "std" : 4 },
      { "grade" : 85, "mean" : 85, "std" : 6 }
   ]
}
{
   "_id" : 2,
   "grades" : [
      { "grade" : 90, "mean" : 75, "std" : 6 },
      { "grade" : 87, "mean" : 90, "std" : 3 },
      { "grade" : 85, "mean" : 85, "std" : 4 }
   ]
}

3) Executed the following command:

db.students2.update(
   { },
   { $set: { "grades.$[elem].mean" : 100 } },
   {
     multi: true,
     arrayFilters: [ { "elem.grade": { $gte: 85 } } ]
   }
)

This resulted in a new error:

code: 2
msg: No array filter found for identifier 'elem' in path 'grades.$[elem].mean'

Pease note that the above have been taking directly from https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/#update-all-documents-that-match-arrayfilters-in-an-array without modifying it the slightest.



 Comments   
Comment by Dominic Kerchner [ 16/Aug/18 ]

Thanks! https://jira.mongodb.org/browse/SERVER-36707

Comment by Kelsey Schubert [ 16/Aug/18 ]

Hi dkerchner,

Yes, please open a new ticket so we can investigate — if you have a reproducer, please include it.

Thank you,
Kelsey

Comment by Dominic Kerchner [ 16/Aug/18 ]

Hi, I am experiencing this issue today with 3.6.6. I have even tried with the samples and I still get the 'array filter not found' error. Should I open a new ticket?

 

Thanks,

Dominic

Comment by Kelsey Schubert [ 23/Mar/18 ]

Hi mlarsson,

We haven’t heard back from you for some time, so I’m going to mark this ticket as resolved. If this is still an issue for you, please provide additional information and we will reopen the ticket.

Regards,
Kelsey

Comment by Kelsey Schubert [ 06/Mar/18 ]

Hi mlarsson@princh.com,

I've also tried to reproduce your second example without any luck. Please see below:

> db.students2.insert({
...    "_id" : 1,
...    "grades" : [
...       { "grade" : 80, "mean" : 75, "std" : 6 },
...       { "grade" : 85, "mean" : 90, "std" : 4 },
...       { "grade" : 85, "mean" : 85, "std" : 6 }
...    ]
... })
WriteResult({ "nInserted" : 1 })
> db.students2.insert({
...    "_id" : 2,
...    "grades" : [
...       { "grade" : 90, "mean" : 75, "std" : 6 },
...       { "grade" : 87, "mean" : 90, "std" : 3 },
...       { "grade" : 85, "mean" : 85, "std" : 4 }
...    ]
... })
WriteResult({ "nInserted" : 1 })
> db.students2.update(
...    { },
...    { $set: { "grades.$[elem].mean" : 100 } },
...    {
...      multi: true,
...      arrayFilters: [ { "elem.grade": { $gte: 85 } } ]
...    }
... )
WriteResult({ "nMatched" : 2, "nUpserted" : 0, "nModified" : 2 })

Would you please confirm that you're still able to reproduce this issue? Have you tried these steps on a brand new collection?

Thank you,
Kelsey

Comment by Morten Larsson [ 01/Mar/18 ]

Hi Ramón. I uploaded something for you now. Kind regards Morten

Comment by Ramon Fernandez Marina [ 22/Feb/18 ]

mlarsson, I am unable to reproduce either behavior; here's a toy example that I think matches your first case:

db.foo.drop()
db.foo.insert(
{
   "_id": 1,
   "documents": [
      {
         "id": "1234",
         "status": "UNTOUCHED"
      },
      {
         "id": "1235",
         "status": "UNTOUCHED"
      },
   ]
})
 
db.foo.insert(
{
   "_id": 2,
   "documents": [
      {
         "id": "1234",
         "status": "UNTOUCHED"
      },
      {
         "id": "1235",
         "status": "UNTOUCHED"
      },
   ]
})
db.foo.find()
 
db.foo.update(
   { },
   { $set: { "documents.$[e].status" : "TOUCHED" } },
   { multi:true, arrayFilters: [ { "e.id": "1234" } ] }
)
 
db.foo.find()
db.serverBuildInfo().version

When I put the above in a test.js file and run mongo < test.js I get:

$ mongo < test2.js
MongoDB shell version v3.6.2
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.2
true
WriteResult({ "nInserted" : 1 })
WriteResult({ "nInserted" : 1 })
{ "_id" : 1, "documents" : [ { "id" : "1234", "status" : "UNTOUCHED" }, { "id" : "1235", "status" : "UNTOUCHED" } ] }
{ "_id" : 2, "documents" : [ { "id" : "1234", "status" : "UNTOUCHED" }, { "id" : "1235", "status" : "UNTOUCHED" } ] }
WriteResult({ "nMatched" : 2, "nUpserted" : 0, "nModified" : 2 })
{ "_id" : 1, "documents" : [ { "id" : "1234", "status" : "TOUCHED" }, { "id" : "1235", "status" : "UNTOUCHED" } ] }
{ "_id" : 2, "documents" : [ { "id" : "1234", "status" : "TOUCHED" }, { "id" : "1235", "status" : "UNTOUCHED" } ] }
3.6.2
bye

Same thing for the example from our docs:

db.foo.drop()
 
db.foo.insert(
{
   "_id" : 1,
   "grades" : [
      { "grade" : 80, "mean" : 75, "std" : 6 },
      { "grade" : 85, "mean" : 90, "std" : 4 },
      { "grade" : 85, "mean" : 85, "std" : 6 }
   ]
})
db.foo.insert(
{
   "_id" : 2,
   "grades" : [
      { "grade" : 90, "mean" : 75, "std" : 6 },
      { "grade" : 87, "mean" : 90, "std" : 3 },
      { "grade" : 85, "mean" : 85, "std" : 4 }
   ]
})
 
db.foo.update(
   { },
   { $set: { "grades.$[elem].mean" : 100 } },
   {
     multi: true,
     arrayFilters: [ { "elem.grade": { $gte: 85 } } ]
   }
)
db.foo.find()

Do you think you can create a reproducer that shows the behavior you're describing? I've also created a secure upload portal if you want to upload a copy of your collection where the behavior reproduces.

Thanks,
Ramón.

Generated at Thu Feb 08 04:33:25 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.