2012-01-31 24 views
3

我有一個鏈接跟蹤表(其他字段中)有track_redirect和track_userid。我想輸出一個給定的鏈接的總數,以及唯一的計數 - 通過用戶ID計數重複。所以我們可以區分是否有人點擊了相同的鏈接5次。如何計算mongo中兩個字段的計數和唯一計數reduce函數

我已經嘗試在鍵和值部分中發射this.track_userid,但無法掌握如何在reduce函數中正確訪問它們。

所以,如果我回滾到時,它實際工作,我有下面的代碼非常簡單 - 就像這將是一個「我的第一個MapReduce的功能」例如

地圖

function() { 
    if(this.track_redirect) { 
    emit(this.track_redirect,1); 
    } 
} 

減少

function(k, vals) { 
    var sum = 0; 
    for (var i in vals) { 
    sum += vals[i]; 
    } 
    return sum; 
} 

我想知道正確的方式來發出額外的userid信息,並在mapreduce中訪問它。還是我以錯誤的方式思考它?

的情況下,目前還不清楚,我不想計算總點擊用戶ID已經提出,但要算上每個URL +用戶ID的獨特的點擊 - 不包括任何重複點擊每一個環節上做了一個用戶ID

有人可以指點我正確的方向嗎?謝謝!

回答

4

實際上你可以在emit調用的第二個參數上傳遞任意對象。這意味着你可以利用這一點,並將用戶標識存儲在其中。例如,您的地圖功能可以是這樣的:

var mapFunc = function() { 
    if (this.track_redirect) { 
    var tempDoc = {}; 
    tempDoc[this.track_userid] = 1; 

    emit(this.track_redirect, { 
     users_clicked: tempDoc, 
     total_clicks: 1 
    }); 
    } 
}; 

而且你的降低作用可能是這樣的:

var reduceFunc = function(key, values) { 
    var summary = { 
    users_clicked: {}, 
    total_clicks: 0 
    }; 

    values.forEach(function (doc) { 
    summary.total_clicks += doc.total_clicks; 
    // Merge the properties of 2 objects together 
    // (and these are actually the userids) 
    Object.extend(summary.users_clicked, doc.users_clicked); 
    }); 

    return summary; 
}; 

摘要對象的users_clicked財產基本上存儲每個用戶的ID作爲屬性(因爲你不能有重複的屬性,你可以保證它會存儲唯一的用戶)。還要注意,您必須注意傳遞給reduce函數的某些值可能是之前reduce的結果,上面的示例代碼考慮到了這一點。您可以在文檔here中找到有關上述行爲的更多信息。

爲了獲得獨特的計數,你可以通過在終結函數被調用時,減少階段完成:

var finalFunc = function(key, value) { 
    // Counts the keys of an object. Taken from: 
    // http://stackoverflow.com/questions/18912/how-to-find-keys-of-a-hash 
    var countKeys = function(obj) { 
    var count = 0; 

    for(var i in obj) { 
     if (obj.hasOwnProperty(i)) 
     { 
     count++; 
     } 
    } 

    return count; 
    }; 

    return { 
    redirect: key, 
    total_clicks: value.total_clicks, 
    unique_clicks: countKeys(value.users_clicked) 
    }; 
}; 

最後,您可以執行地圖縮小喜歡這份工作(修改out屬性來適合你的需求):

db.users.mapReduce(mapFunc, reduceFunc, { finalize: finalFunc, out: { inline: 1 }}); 
+0

謝謝仁,那是完全正確的。這個例子很好的使用了我的數據 - 就像我現在真正理解的那樣!非常好的第一個stackoverflow答案matey! – joevallender 2012-02-01 09:46:27

+0

如果有人在這個線程中發現了這個問題,這可能是有用的:我寫了Ren的答案,包括顯示每個階段之間的數據http://scriptogr.am/joevallender/post/simple-introduction-to-mapreduce-using-mongodb – joevallender 2012-06-14 12:53:03