2010-06-09 81 views
12

第一次地图/减少用户在这里,并使用MongoDB。我有很多页面访问数据,我想通过使用Map/Reduce来了解一些情况。下面基本上是我想要做的,但作为一个初学者Map/Reduce,我认为这超出了我的知识!Mongo Map第一次减少

  1. 浏览所有在过去30天内访问的页面,以及external = true的位置。
  2. 然后为每个页面,找到所有访问
  3. 集团转诊位置
  4. 所有访问对于每个推荐的位置,计算出许多那么如何去拜访它具有一定的“类型”页面,也具有一定的词在“标签”中。

数据库和收集组织为

$mongo->dbname->visits 

样本文件是:

{"url": "www.example.com", "type": "a", "refer": {"external": true, "domain": "twitter.com", "url": "http://www.twitter.com/page"}, "page": "1235", "user": "1232", "time": 1234567890} 

然后,我想找到某种标签B类型的文档。

{"url": "www.example.com", "type": "b", "page": "745", "user": "1232", "time": 1234567890, "tags": {"a", "b", "c"}} 

我正在使用正常的Mongo PHP扩展,如果这有影响。

+1

你有什么数据库结构?你的收藏和文件是如何组织的? – 2010-06-09 04:46:51

+0

添加到上面的帖子。这种帮助? – James 2010-06-09 12:01:01

+0

好的,您的示例文档不包含“推荐”,“外部”或“标签”字段。 你的建议确实很复杂,所以你可能需要向我们展示多个文档。你可能需要显示所有的细节。 – 2010-06-10 05:43:02

回答

16

好吧,我想出了一些东西,我认为可以做你想做的。请注意,这可能无法正常工作,因为我不能100%确定您的模式(考虑到您的示例显示refer可用于类型a,但不是b(我不确定这是否是遗漏,或者考虑您想要鉴于引用者)......总之,这里是我想出来的:

地图功能:

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

精简函数:

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

因此,基本上,它是如何工作是这样的,Map函数使用了一个refer.url键(我根据你的描述猜测出来的) ription)。所以最终的结果看起来像一个_id等于refer.url的数组(它基于url)。然后它创建一个包含两个对象(类型和标签)的对象。该对象的原因是,map和reduce可以发出相同的格式对象。除此之外,我认为这应该是相对自我解释(如果你不明白,我可以尝试解释更多)...

所以让我们在PHP中实现这一点(假设$map$reduce是字符串以上包含了他们的简洁):

$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"; 
} 

注意,我没有测试过这个。这仅仅是我想出根据我对你的架构的了解,并从我的蒙戈和其映射简化实施谅解......

+0

$ statsCollection = $ db-> selectCollection($ sales ['result']); $ sales? – Tobias 2011-07-13 01:04:47