Thursday, December 19, 2013

Mongo Aggregating Fractals.

Here's a Holiday season special for you - can you do complex iterative calculation with the Aggregation Framework in MongoDB? - of course you can.

First set.


DBQuery.shellBatchSize = 500

Then paste the following into a Mongo Shell, Set it to a very tiny font to view the output.

db.img.drop()
iters = 1000

for (x=-1.5;x<1;x=x+0.03){
 for (y=-1.1;y<1;y=y+0.01){
    db.img.insert({'cr':x,'ci':y,'zr':x,'zi':y,'it':0})
  }
 }

zrsquare = {'$multiply' : [ '$zr','$zr' ]};
zisquare =  {'$subtract' : [ 0 , {'$multiply' : [ '$zi','$zi' ]}]};
zixzrx = { '$multiply' : [{'$multiply' : [ '$zr','$zi' ]},2]};
inciflow = { '$cond' : [ { '$lte' : [ '$zr' , 4 ]} , 1 , 0] };
itterate = { '$project' :
    { 
        'cr' : 1,
        'ci' : 1 ,
        'zr' : { '$add' : [ zrsquare , zisquare, '$cr']},
        'zi' : { '$add' : [ zixzrx, '$ci' ] } ,
        'it' : { '$add' : [ "$it" , inciflow]}
    } 
};

pipeline =[];
for(i=0;i<iters;i++){ pipeline.push(itterate);}
pipeline.push({ '$group' : { '_id' :'$ci','r' : { '$push' : { '$cond' : [{ '$lt' : [ '$it', iters]},88888,1]}}}});
pipeline.push({ '$sort' : { '_id' : 1 }});
pipeline.push({'$project':{ '_id' : 0, r : 1}});

db.img.aggregate(pipeline);


The output - well it looks a bit like this,







2 comments:

Alain Helaili said...

After doing this, he actually looked at me and said : "I think I can program a Tetris using the aggregation framework". No need to say I was speechless.

John, you're amazing.

John Page said...

For those of you having difficulty getting it to output right, Derrick Rethans suggests changing 88888 and 1 to '88888' and ' ' (5 spaces). This fixes layout for those where for some readon the aligned number output doesnt work.