|
// 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" ] ] }, |
|
}, |
|
}, |
|
} } } } |
|
] ); |