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

Mongo Map-Reduce To Mimic count (distinct(...)) group by in SQL

Du kan nemt samle resultatet i stedet for at vælge en kortreducerende løsning:

  • Match de poster, hvor datoen er større end lig med den angivne dato.

  • Group baseret på brand_id felt.

  • Brug $addToSet operatør til at vedligeholde et products liste over unikt product_id for hver gruppe.

  • Project count af products array i hver tast.

Kode:

db.collection.aggregate([
{$match:{"date":{$gte:new Date('2014-11-20')}}},
{$group:{"_id":"$brand_id","products":{$addToSet:"$product_id"}}},
{$project:{"_id":0,"brand_id":"$_id","distinct_prod":{$size:"$products"}}}
])

Kommer til din kortreducerende løsning,

Det er en måde, mongodb kan påberåbe reduktionsfunktionen for hver gruppe. Fra dokumenterne :

Du skal lave nogle ændringer på dit map ,reduce funktioner og tilføje en ny finalize funktion:

  • Du skal huske, at når mongodb påberåber reduce funktion for den samme tast mere end én gang, sendes resultatet af den forrige påkaldelse som input til reduktionsfunktionen sammen med de andre værdier, næste gang reduktionsfunktionen aktiveres.
  • Første punkt, så du skal sikre dig, at input til reduceringsfunktionen og returværdien fra reduceringsfunktionen er konstrueret på samme måde, så logikken skrevet inde i reducerfunktionen kan rumme behandling af dens egen returnerede værdi i dens tidligere kald.
  • Da vi ikke ville være i stand til at hente antallet af distinkte værdier, når de kaldes i batches, kan vi skrive en reduce funktion, der akkumulerer de distinkte product_ids for hver tast og skriv enfinalize funktion, der beregner antallet af disse unikke værdier.

Kode:

db.collection.mapReduce(
    function() {
        // emitting the same structure returned by the reduce function.
        emit(this.brand_id, {"prod_id":[this.product_id]});
    },
    function(key, values) {
       // the return value would be a list of unique product_ids.
        var res = {"prod_id":[]};
        for(var i=0;i<values.length;i++)
        {
         for(var j=0;j<values[i].prod_id.length;j++){
            if(res.prod_id.indexOf(values[i].prod_id[j]) == -1){
                res.prod_id.push(values[i].prod_id[j]);
            }
        }}
        return res;
    },
    {
        query: {date: {$gte: new Date('2014-11-20')}},
        out: "example",
        finalize: function(key, reducedValue){
            // it returns just the count
            return reducedValue.prod_id.length;
        }
    }
)



  1. NodeJS tilbagekald efter flere async-funktioner i for-loop

  2. Hvordan bruger man $hint i MongoDB aggregeringsforespørgsel?

  3. Referencer vs indlejring i MongoDB

  4. Hvordan konfigurerer jeg mongo til at køre i docker til at bruge et eksternt drev på Windows