Details
-
Improvement
-
Resolution: Unresolved
-
Major - P3
-
None
-
None
-
None
-
None
-
Query Optimization
-
(copied to CRM)
Description
I couldn't find a way to update a nested array matching a specific query when using the aggregation pipeline for update operations.
Example :
I have the following data :
"_id" : ObjectId("5fd3ba7eb0b91523b424e612"), |
"data-block-array" : |
[
|
{
|
"block-id" : ObjectId("5fd3ba7eb0b91523b424e614") |
"metadata" : {...}, |
"data-value" : "Current value" |
},
|
{
|
"block-id" : ObjectId("5fd3ba7eb0b91523b424e616") |
"metadata" : {...}, |
"data-value" : "" |
}
|
]
|
I want to update the data-value of the data block with "block-id" : ObjectId("5fd3ba7eb0b91523b424e614") for the document with "_id" : ObjectId("5fd3ba7eb0b91523b424e612").
With the "classical" update (without pipeline), I can do :
db.getCollection('myCollection').updateOne( |
{
|
"_id" : ObjectId("5fd3ba7eb0b91523b424e612"), |
"data-block-array.block-id": ObjectId("5fd3ba7eb0b91523b424e614") |
},
|
{
|
$set :
|
{
|
"data-block-array.$."data-value" : "New value" |
}
|
}
|
)
|
But with the following aggregation pipeline, that fails :
db.getCollection('myCollection').updateOne( |
{
|
"_id" : ObjectId("5fd3ba7eb0b91523b424e612"), |
"data-block-array.block-id": ObjectId("5fd3ba7eb0b91523b424e614") |
},
|
{
|
$set :
|
{
|
"data-block-array.$."data-value" : "New value" |
}
|
}
|
)
|
I get the error :
"Invalid $set :: caused by :: FieldPath field names may not start with '$'."
We also cannot use arrayFilters in an aggregation pipeline.
I've seen in the issue SERVER-40397 that you will never implement arrayFilters for the update with aggregation pipeline, but could you add the support for positional $ operator ?
I could use the other update version, but when you have in implementation (in C++ in my case) where we use polymorphism with a class method that returns a pipeline - which also supports things that we can't do with the other version - , it may be difficult to do so.