sql >> Databáze >  >> NoSQL >> MongoDB

vypočítat frekvenci pomocí agregovaného rámce mongodb

Pokud jde jen o to, dostat věci do 10 sekundových intervalů, můžete si trochu spočítat a projít to souhrnem:

db.collection.aggregate([
    { "$group": {
        "_id": {
             "year": { "$year": "$created_at" },
             "month":{ "$month": "$created_at" },
             "day": { "$dayOfMonth": "$created_at" },
             "hour": { "$hour": "$created_at" },
             "minute": { "$minute": "$created_at" },
             "second": { "$subtract": [
                 { "$second": "$created_at" },
                 { "$mod": [
                     { "$second": "$created_at" },
                     10
                 ]}
             ]}
        },
        "count": { "$sum" : 1 }
    }}
])

Takže to rozdělí věci na intervaly 10 sekund za minutu, kde k nim dochází s trochou matematického modu 10.

Myslím, že je to rozumné a byl by to nejrychlejší běžec, protože používá agregát. Pokud opravdu potřebujete, aby vaše sekvence, jak je ukázána, běžela 10 sekund od původně shodného času, můžete proces provést pomocí mapReduce:

Nejprve mapovač:

var mapper = function () {

    if ( this.created_at.getTime() > ( last_date + 10000 ) ) {
        if ( last_date == 0 ) {
            last_date = this.created_at.getTime();
        } else {
            last_date += 10000;
        }
    }

    emit(
        {
            start: new Date( last_date ),
            end: new Date( last_date + 10000 )
        },
        this.created_at
    );

}

Takže to bude vydávat data v intervalu 10 sekund, počínaje prvním datem a pak se interval prodlužuje pokaždé, když je něco nalezeno mimo rozsah

Nyní potřebujete redukci:

var reducer = function (key, values) {
    return values.length;
};

Velmi jednoduché. Stačí vrátit délku předávaného pole.

Protože mapReduce funguje tak, jak funguje, nic, co nemělo více než jednu hodnotu, není předáno do reduktoru, takže to vyčistěte pomocí finalize:

var finalize = function (key, value) {
    if ( typeof(value) == "object" ) {
        value = 1;
    }
    return value;
};

Pak to stačí spustit, abyste získali výsledky. Všimněte si sekce "rozsah", která předává globální proměnnou, která má být použita v mapovači:

db.collection.mapReduce(
    mapper,
    reducer,
    { 
        "out": { "inline": 1 }, 
        "scope": { "last_date": 0 }, 
        "finalize": finalize 
    }
)

Každý přístup pravděpodobně poskytne mírně odlišné výsledky, ale o to jde. Záleží na tom, který z nich skutečně chcete použít.

Vzhledem k vašemu komentáři byste mohli buď "zkontrolovat" výstup z kteréhokoli prohlášení a "doplnit mezery" programově. Obecně dávám přednost této možnosti, ale není to můj program a nevím, jak velkou sérii se snažíte z tohoto dotazu získat.

Na straně serveru můžete opravit "mapovač" a provést něco takového:

var mapper = function () {

    if ( this.created_at.getTime() > ( last_date + 10000 ) ) {

        if ( last_date == 0 ) {
            last_date = this.created_at.getTime();
        } else {
            // Patching for empty blocks
            var times = Math.floor( 
                 ( this.created_at.getTime() - last_date ) / 10000
            );

            if ( times > 1 ) {
                for ( var i=1; i < times; i++ ) {
                    last_date += 10000;
                    emit(
                        {
                            start: new Date( last_date ),
                            end: new Date( last_date + 10000 )
                        },
                        0
                    );
                }
            }
            // End patch
            last_date += 10000;
        }
    }

    emit(
        {
            start: new Date( last_date ),
            end: new Date( last_date + 10000 )
        },
        this.created_at
    );

}



  1. MongoDB $dayOfWeek

  2. Filtrovat pole vnořených dokumentů a stále vracet nadřazená data, pokud jsou prázdná

  3. Propojování a vytváření spojení MongoDB pomocí SQL:Část 1

  4. Mongodb – Rozdíl mezi spuštěnými databázemi mongo a mongod