Monday, May 29, 2017

C# Mongodb cartesian product of multiple object array documents

Leave a Comment

Trying to understand with either C#/Linq or even raw Mongodb query itself how to join multiple arrays as a cartesian product.

Say for example I had a collection that I filtered down to the following two documents:

[ {"movie":"starwars","showday":"monday"}, {"movie":"batman","showday":"thursday"}, {"movie":"sleepless","showday":"tuesday"} ]  [ {"actor":"angelina","location":"new york"}, {"actor":"jamie","location":"california"}, {"actor":"mcavoy","location":"arizona"} ] 

How can I join each item in each array to produce the following type of result?

[{"movie":"starwars","showday":"monday","actor":"angelina","location":"new york"}, {"movie":"batman","showday":"thursday","actor":"angelina","location":"new york"}, {"movie":"sleepless","showday":"tuesday","actor":"angelina","location":"new york"}, {"movie":"starwars","showday":"monday","actor":"jamie","location":"california"}, {"movie":"batman","showday":"thursday","actor":"jamie","location":"california"}, {"movie":"sleepless","showday":"tuesday","actor":"jamie","location":"california"}, {"movie":"starwars","showday":"monday","actor":"mcavoy","location":"arizona"}, {"movie":"batman","showday":"thursday","actor":"mcavoy","location":"arizona"}, {"movie":"sleepless","showday":"tuesday","actor":"mcavoy","location":"arizona"}] 

I am looking for a solution that could work with any number of documents. So for example if in this example there was a 3rd document that also had 3 object arrays that would produce a result set of 27 items in the array - or 27 rows as it were.

Hoping for a solution of how to use C# (Linq?) Mongodb Driver to query and return data like this but would be open to even a mongodb specific query as I can hopefully reverse the logic from there. thank you

1 Answers

Answers 1

You can try below aggregation pipeline.

Note mergeObjects aggregation operator is available in the 3.5.6 + development release which will be rolled into upcoming 3.6 release.

db.collection.find(); {  "data" : [   [    {     "movie" : "starwars",     "showday" : "monday"    },    {     "movie" : "batman",     "showday" : "thursday"    },    {     "movie" : "sleepless",     "showday" : "tuesday"    }   ],   [    {     "actor" : "angelina",     "location" : "new york"    },    {     "actor" : "jamie",     "location" : "california"    },    {     "actor" : "mcavoy",     "location" : "arizona"    }   ]  ] } 

Aggregation:

aggregate({  $project: {   cp: {    $reduce: {     input: "$data",     initialValue: {      $arrayElemAt: ["$data", 0] // Set the initial value to the first element of the arrays.     },     in: {      $let: {       vars: {        currentr: "$$this", // Current processing element        currenta: "$$value" // Current accumulated value        },       in:{         $reduce: {         input: {          $map: {           input: "$$currenta",           as: "a",           in: {            $map: {             input: "$$currentr",             as: "r",             in: {              $mergeObjects: ["$$a", "$$r"] // Merge accumulated value with the current processing element             }            }           }          }         },         initialValue: [],         in: {          $setUnion: ["$$value", "$$this"] // Reduce the merged values which will be used as accumulator for next element         }        }       }      }     }    }   }  } }); 

Reference: Cartesian product of multiple arrays in JavaScript

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment