sql >> Databasteknik >  >> NoSQL >> MongoDB

Mongo Karta Reducera första gången

Ok, jag har kommit på något som jag tror får göra vad du vill. Observera att detta kanske inte fungerar exakt eftersom jag inte är 100 % säker på ditt schema (med tanke på att dina exempel visar refer tillgänglig i typ a, men inte b (jag är inte säker på om det är ett utelämnande eller vad du vill se av referent)... Hur som helst, här är vad jag har kommit fram till:

Kartfunktionen:

function() {
    var obj = {
        "types": {},
        "tags": {},
    }
    obj.types[this.type] = 1;
    if (this.tags) {
        for (var tag in this.tags) {
            obj.tags[this.tags[tag]] = 1;
        }
    }
    emit(this.refer.url, obj);
}

Funktionen Reducera:

function(key, values) {
    var obj = {
        "types": {},
        "tags": {},
    }
    for (var i = 0; i < values.length; i++) {
        for (var type in values[i].types) {
            if (!type in obj.types) {
                obj.types[type] = 0;
            }
            obj.types[type] += values[i].types[type];
        }
        for (var tag in values[i].tags) {
            if (!tag in obj.tags) {
                obj.tags[tag] = 0;
            }
            obj.tags[tag] += values[i].tags[tag];
        }
    }
    return obj;
}

Så i grund och botten, hur det fungerar är detta. Kartfunktionen använder nyckeln refer.url (vad jag gissade utifrån din beskrivning). Så slutresultatet kommer att se ut som en array med _id lika med refer.url (den grupperar baserat på url). Den skapar sedan ett objekt som har två objekt under sig (typer och taggar). Anledningen till objektet är så att map och reducer kan sända ut samma formatobjekt. I övrigt tycker jag att det borde vara relativt självförklarande (om du inte förstår kan jag försöka förklara mer)...

Så låt oss implementera detta i PHP (förutsatt att $map och $reduce är strängar med ovanstående inkluderat med dem för konsistens):

$mapFunc = new MongoCode($map);
$reduceFunc = new MongoCode($reduce);
$query = array(
    'time' => array('$gte' => time() - (60*60*60*24*30)),
    'refer.external' => true
);
$collection = 'visits';
$command = array(
    'mapreduce' => $collection,
    'map' => $mapFunc,
    'reduce' => $reduceFunc,
    'query' => $query,
);

$statsInfo = $db->command($command);

$statsCollection = $db->selectCollection($sales['result']);

$stats = $statsCollection->find();

foreach ($stats as $stat) {
    echo $stats['_id'] .' Visited ';
    foreach ($stats['value']['types'] as $type => $times) {
        echo "Type $type $times Times, ";
    }
    foreach ($stats['value']['tags'] as $tag => $times) {
        echo "Tag $tag $times Times, ";
    }
    echo "\n";
}

Obs, jag har inte testat detta. Det här är bara vad jag har kommit fram till baserat på min förståelse av ditt schema och från min förståelse av Mongo och dess Map-Reduce-implementering...



  1. Hitta alla dubbletter av dokument i en MongoDB-samling genom ett nyckelfält

  2. Hanterar schemaändringar i Mongoose

  3. MongoDB Aggregation:lägg till fält från ett inbäddat dokument via en dynamisk fältsökväg

  4. vad är mongodb arkivformat?