2010-06-09 117 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