Effectively calculate percentage of occurrence in MongoDB

So, I was messing around with MongoDB, and I'm trying to get the aggregation queries scaled correctly count()so that I can easily calculate the percentage of occurrence of certain values ​​in a collection document.

I have a document with a structure like:

{
    foo : 'bar',
    moo : 'cow',
    values : {
        alpha : true,
        beta : false,
        gamma : false,
        delta : true ... (many more)
    }
}

Now I have several thousand of these documents, and I want to efficiently calculate the percentage of true (or percentage false) of all values ​​in the object values(and in my case there are ~ 50). those. what percentage of alpha time is true, beta is true, etc.

I started naively with count(), but it looks like it only allows one request at a time, so that led me to this (using the PHP Mongo class, but its basically just a regular function count():

 $array_of_keys = array('alpha', 'beta', 'gamma', 'delta'...);
 for($i=0;$i<count($array_of_keys);$i++){
    $array_of_keys = [...]
    for($i=0;$i<count($array_of_keys);$i++){

$false  = intval($collection->count(array($array_of_keys[$i]=>false)));
$true  = intval($collection->count(array($array_of_keys[$i]=>true)));
}

( 100) 9 .

?

+3
1

MapReduce, , :

map = function() {
    for (var key in this.values){
        emit(key, {count:1, trues: (this.values[key] ? 1 : 0)});
    }
}

reduce = function(key, values){
    var out = values[0];
    for (var i=1; i < values.length; i++){
        out.count += values[i].count;
        out.trues += values[i].trues;
    }
    return out;
}

finalize = function(key, value){
    value.ratio = value.trues / value.count;
    return value;
}

db.runCommand({mapReduce:'collection',
               map:map,
               reduce:reduce,
               finalize:finalize,
               out:'counts'
               })

db.counts.findOne({_id:'alpha'})
{_id: 'alpha', value: {count: 100, trues: 52, ratio: 0.52}}

upsert, , , :

for (var key in this.values){
    db.counts.update({_id:key},
                     {$inc:{count:1, trues: (this.values[key] ? 1 : 0)}},
                     true);
}

. MapReduce, counts, upserts, .

+5

Source: https://habr.com/ru/post/1788064/


All Articles