Mongo query assistance update array element with field from object

Got it, I think. But it needs https://docs.mongodb.com/manual/tutorial/update-documents-with-aggregation-pipeline/ from 4.2.

It’s kind of complicated. It is going to be a update pipeline with a $set stage that uses $map. It will update the products array into a temporary updated_products array, but you could $map in itself. I like the temp. field as in Tip3.express

// Apply the mapping only to document that needs it (see Tip 2)
update_query =
{ "products.product.type" : "plan" ,
  "products.product.plan_group" : { "$type" : "string" }
}

// update_plan_group replace plan_group which is a string to an array but keeps the
// old price and type ($$item is the ***as*** of the $map)
update_plan_group =
{  "product" :
  { "plan_group" : [ "$$item.product.plan_group" ] ,
    "price" : "$$item.product.price" ,
    "type" : "$$item.product.plan"
  }
}

// We want to only alter the product when plan_group is a string.  You might want to
// check for type:plan in case you have string plan_group for something else than plan
plan_group_is_string ={ "$eq" : [ { "$type":"$$item.product.plan_group"} , "string" ] }

// We map plan_group only when plan_group is a string
conditional_mapping =
{ '$cond' :
  { 'if' : plan_group_is_string ,
    "then" : update_plan_group ,
    "else" : "$$item"
  }
}
// Map the products array. This is where we defined $$item used above.
map =
{  "$map" :
  { "input" : "$products" ,
    "as" : "item" ,
    "in" : conditional_mapping 
  }
}

// Let's do it in a temporary array named updated_products. See Tip 3.
// You will need to move updated_products into products in
// another step but you get the chance to verify the result before and make any
// without losing the original values
update_pipeline = [ { "$set" : { "mapped_products" : map } } ]
c.updateMany( updateQuery , update_pipeline )upda

// The complete update_pipeline is:
[ { '$set': 
     { mapped_products: 
        { '$map': 
           { input: '$products',
             as: 'item',
             in: 
              { '$cond': 
                 { if: { '$eq': [ '$$item.product.type', 'plan' ] },
                   then: 
                    { product: 
                       { plan_group: [ '$$item.product.plan_group' ],
                         price: '$$item.product.price',
                         type: '$$item.product.plan' } },
                   else: '$$item' } } } } } } ]

// The updated document is
{ _id: 1,
  number: 'CC850732',
  products: 
   [ { product: { plan_group: 'Old', price: 1999, type: 'plan' } },
     { product: { price: 1999, type: 'other' } },
     { product: { plan_group: 'New', price: 1999, type: 'plan' } } ],
  updated_products: 
   [ { product: { plan_group: [ 'Old' ], price: 1999 } },
     { product: { price: 1999, type: 'other' } },
     { product: { plan_group: [ 'New' ], price: 1999 } } ] }

Enjoy!