|  | // It's possible to use $reduce to handle the "insert a document | 
        
          |  | // immediately after (or before) a matching document" use case: | 
        
          |  | db.marching_order.updateOne( { _id : 'column-one' }, [ | 
        
          |  | { $set : { marchers : { $reduce : { | 
        
          |  | input         : '$marchers', | 
        
          |  | initialValue  : [], | 
        
          |  | in            : { | 
        
          |  | // iterate through the marchers list (an array of documents with | 
        
          |  | // a name property), and apply the rules in this $switch to each | 
        
          |  | // matching person that we find... | 
        
          |  | $switch : { | 
        
          |  | // Within the `$reduce`, the `$$this` variable refers to the | 
        
          |  | // current element of the list, and the `$$value` variable is | 
        
          |  | // the accumulator..  For JavaScript devs it's something like: | 
        
          |  | // $marchers.reduce( ( $$value, $$this ) => {} ); | 
        
          |  | branches  : [ | 
        
          |  | { | 
        
          |  | // When we find "Bob"... | 
        
          |  | case : { $eq : [ "$$this.name", "Bob" ] }, | 
        
          |  | // we want to add "Alice" right before him | 
        
          |  | then : { $concatArrays : [ | 
        
          |  | // Note that the accumulator is already an array | 
        
          |  | // (because of the `initialValue : []` up at the | 
        
          |  | // beginning)... | 
        
          |  | "$$value", | 
        
          |  | // But for other values we need to wrap them in an | 
        
          |  | // array. | 
        
          |  | [ { name : "Alice", age : 11 } ], | 
        
          |  | [ "$$this" ], | 
        
          |  | ] }, | 
        
          |  | }, | 
        
          |  | { | 
        
          |  | // When we find "Chuck"... | 
        
          |  | case : { $eq : [ "$$this.name", "Chuck" ] }, | 
        
          |  | // we're going to add 4 people behind him | 
        
          |  | then : { $concatArrays : [ "$$value", [ | 
        
          |  | "$$this", | 
        
          |  | { name : "Dave", age : 20 }, | 
        
          |  | { name : "Dave Too", age : 19 }, | 
        
          |  | { name : "Also Dave", age : 17 }, | 
        
          |  | { name : "Elwood", age : 43 }, | 
        
          |  | ] ] }, | 
        
          |  | }, | 
        
          |  | { | 
        
          |  | // We're also going to remove everyone from the list who | 
        
          |  | // is bad at marching | 
        
          |  | case : { $or : [ | 
        
          |  | // Zeke is terrible at marching | 
        
          |  | { $eq : [ "$$this.name", "Zeke" ] }, | 
        
          |  | // Everyone under 3 just gets in the way | 
        
          |  | { $lt : [ "$$this.age", 3 ] }, | 
        
          |  | // Everyone over 100 ends up needing a wheelchair | 
        
          |  | { $gt : [ "$$this.age", 100 ] }, | 
        
          |  | ] }, | 
        
          |  | // Returning the accumulator without adding "$$this" to it | 
        
          |  | // effectively removes that item from the list. | 
        
          |  | then : "$$value", | 
        
          |  | }, | 
        
          |  | ], | 
        
          |  | // The default if none of the branches matched is to just add | 
        
          |  | // that item the accumulator. | 
        
          |  | default : { $concatArrays : [ "$$value", [ "$$this" ] ] }, | 
        
          |  | }, | 
        
          |  | }, | 
        
          |  | } } } } | 
        
          |  | ] ); |