sql >> Database teknologi >  >> NoSQL >> MongoDB

beregne frekvens ved hjælp af mongodb aggregatramme

Hvis det kun handler om at få tingene inden for 10 sekunders intervaller, kan du lave lidt matematik og køre dette gennem aggregeret:

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 }
    }}
])

Så det bryder tingene ned til intervaller på 10 sekunder i et minut, hvor de opstår med lidt mod 10 matematik.

Jeg synes, det er rimeligt, og det ville være den hurtigste løber, da den bruger aggregat. Hvis du virkelig har brug for, at din sekvens som vist er en løbende 10 sekunder fra en oprindeligt matchet tid, så kan du gøre processen med mapReduce:

Først en kortlægger:

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
    );

}

Så dette kommer til at udsende datoer inden for et 10 sekunders interval, begyndende med den første dato og derefter øge intervallet, hver gang noget er fundet uden for rækkevidde

Nu skal du bruge en reduktion:

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

Meget simpelt. Du skal blot returnere længden af ​​det array, der er sendt ind.

Fordi mapReduce fungerer, som det gør, overføres alt, der ikke har mere end én værdi, ikke til reduceringen, så ryd op i dette med afslutte:

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

Så bare kør den for at få resultaterne. Bemærk afsnittet "omfang", der sender en global variabel, der skal bruges i mapper:

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

Hver tilgang vil sandsynligvis give lidt forskellige resultater, men det er pointen. Det afhænger af, hvilken en du rent faktisk vil bruge.

I betragtning af din kommentar kan du enten "inspicere" outputtet fra begge udsagn og "udfylde hullerne" programmatisk som det var. Jeg foretrækker generelt den mulighed, men det er ikke mit program, og jeg ved ikke, hvor stor en serie du forsøger at hente fra denne forespørgsel.

På serversiden kan du lappe "mapperen" for at gøre noget som dette:

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. Udfør MongoTemplate.aggregate uden rækkehentning

  2. Mongodb:flere samlinger eller en stor samling med indeks

  3. MongoDB-forespørgsel med elemMatch til indlejrede array-data

  4. mongodb:skal jeg altid bruge indstillingen 'sikker' på opdateringer