Ok, mir ist etwas eingefallen, was ich denke darf machen was du willst. Beachten Sie, dass dies möglicherweise nicht genau funktioniert, da ich mir Ihres Schemas nicht 100 % sicher bin (in Anbetracht Ihrer Beispiele zeigen Sie refer
verfügbar in Typ a, aber nicht b (ich bin mir nicht sicher, ob das eine Auslassung ist oder was, wenn man bedenkt, dass Sie nach Referrer anzeigen möchten) ... Wie auch immer, hier ist, was ich mir ausgedacht habe:
Die Kartenfunktion:
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);
}
Die Reduce-Funktion:
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;
}
So funktioniert es im Grunde so. Die Kartenfunktion verwendet einen Schlüssel von refer.url (was ich aufgrund Ihrer Beschreibung vermutet habe). Das Endergebnis sieht also wie ein Array mit _id
aus gleich refer.url (gruppiert nach URL). Dann erstellt es ein Objekt, das zwei Objekte darunter hat (Typen und Tags). Der Grund für das Objekt ist, dass Map und Reduce das gleiche Formatobjekt ausgeben können. Abgesehen davon denke ich, dass es relativ selbsterklärend sein sollte (wenn Sie es nicht verstehen, kann ich versuchen, mehr zu erklären) ...
Lassen Sie uns dies also in PHP implementieren (vorausgesetzt, dass $map
und $reduce
sind Strings, in denen das obige der Kürze halber enthalten ist):
$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";
}
Achtung, ich habe das nicht getestet. Dies ist genau das, was ich mir aufgrund meines Verständnisses Ihres Schemas und meines Verständnisses von Mongo und seiner Map-Reduce-Implementierung ausgedacht habe ...