-
Type: Improvement
-
Resolution: Unresolved
-
Priority: Major - P3
-
None
-
Affects Version/s: None
-
Component/s: None
-
None
-
Query Optimization
-
(copied to CRM)
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.