sql >> Databasteknik >  >> NoSQL >> MongoDB

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

Du kan enkelt aggregera resultatet istället för att välja en kartreducerande lösning:

  • Match de poster där datumet är större än det angivna datumet.

  • Group baserat på brand_id fältet.

  • Använd $addToSet operatör för att underhålla en products lista över unika product_id för varje grupp.

  • Project count av products array i varje tangent.

Kod:

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 till din kartreducerande lösning,

Det är ett sätt som mongodb kan anropa reduceringsfunktionen för varje grupp. Från dokumenten :

Du måste göra några ändringar på din map ,reduce funktioner och lägg till en ny finalize funktion:

  • Du måste komma ihåg att när mongodb anropar reduce funktionen för samma tangent mer än en gång skickas resultatet av föregående anrop som en ingång till reduceringsfunktionen, tillsammans med de andra värdena nästa gång reduceringsfunktionen anropas.
  • Första punkten, så du måste se till att indata till reduceringsfunktionen och returvärdet från reduceringsfunktionen är konstruerade på liknande sätt, så att logiken som skrivits inuti reduceringsfunktionen kan rymma bearbetning av dess eget returnerade värde i dess tidigare anrop.
  • Eftersom vi inte skulle kunna hämta antalet distinkta värden när de anropas i batcher, kan vi skriva en reduce funktion som samlar de distinkta product_ids för varje nyckel och skriv en finalize funktion som beräknar antalet av dessa unika värden.

Kod:

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. MongoDB $atan

  2. Replikera endast dokument där {'public':true} i MongoDB

  3. Mongoimport ignorera inledande nolla i csv

  4. Hur gör man icke-CRUD och icke-grundläggande MongoDB-kommandon i ObjCMongoDB?