2014-08-29 43 views
0

我有一個大的MongoDB數據庫,因爲試圖計數文檔使其落下,我需要做的這個函數T的工作:檢查相同的數據沒有按預期

查詢:

M_logs[from] 
     .find() 
     .select('referer') 
     .where('time') 
     .gt(lower_bound) 
     .lt(upper_bound); 

這給我(降低,實際數據> 1K文件):

[ { _id: 53db8f924a1cb7d34a0001e3, referer: '' }, 
    { _id: 53dbe3ef4a1cb7655b008f4d, referer: '' }, 
    { _id: 53dbe3ef4a1cb7655b008f4e, referer: '' }, 
    { _id: 53dbe3ef4a1cb7655b008f4f, 
    referer: 'http://www.url1.com' 
    { _id: 53dbe3ef4a1cb7655b008f50, 
    referer: 'http://url1.com' }, 
    { _id: 53dbe3ef4a1cb7655b008f51, 
    referer: 'http://www.url1.com' } 
    { _id: 53dbe3ef4a1cb7655b008f52, 
    referer: 'http://www.url1.com' }, 
    { _id: 53dbe3ef4a1cb7655b008f53, 
    referer: 'http://www.url1.com' 
    { _id: 53ed5bc64a1cb7f78c00361e, 
    referer: 'http://url1.com' }, 
    { _id: 53ef80384a1cb7019c0000c5, 
    referer: 'http://url2'} 
] 

正如你所看到的,一些日誌車和空的,有些還以www前綴的URL,有的沒有。因爲我需要顯示每個網址給了我們多少訪問者,所以我需要解析它們以僅獲取'url1.com','url2.com',並忽略空字段。並統計每個出現的時間。

代碼是:

function referer_process(result, referer, index, j, callback) { 

    var ur, 
     host; 

    result.forEach(function (element) { 
     ur = url.parse(element.referer, false, false); 

     if (ur.host) { 
      if (ur.host.search('www.') === 0) { 
       host = ur.host.substring(4); 
      } else { 
       host = ur.host; 
      } 
      if (!index[host]) { 
       console.log('.' + host + '. ' + host.length); 
       index[host] = j; 
       j = j + 1; 
       referer[index[host]] = {name: host, y: 1}; 
      } else { 
       referer[index[host]].y = referer[index[host]].y + 1; 
      } 
     } 
    }); 

    callback(referer, index, j); 

} 

出現問題時,我們看到的結果是,如果result有前兩行用相同的引薦(解析一次),其中一人被分配到不同的數,但一切否則會很好。

例子:

url1.com: 5 
url1.com: 1 
url2.com: 1 

我不明白,它如何發生的,是的forEach同步,所以當它遇到URL1第二次必須已創建索引!

這是怎麼發生的?我在哪裏可以搜索解決方案?

回答

0

我建議你要做的是在mongo shell中使用mapReduce來代替這些類型的問題。這裏是你如何使用它:

TIME_UPPER_BOUND = ... 
TIME_LOWER_BOUND = ... 

var map = function() { 
    var host = this.referer; 
    if (host && host.substring(0, 4) == 'http') { 
     host = host.substring(7); 
    } 
    if (host && host.substring(0, 3) == 'www') { 
     host = host.substring(4); 
    } 
    emit(host, 1); 
}; 

var reduce = function(key, values) { 
    return Array.sum(values); 
}; 

var option = { 
    query: {time: {$gt: TIME_LOWER_BOUND, $lt: TIME_UPPER_BOUND}}, 
    out: {inline: 1}, 
}; 

db.refers.mapReduce(map, reduce, option).results; 

有了你上面提供的數據,這將輸出:

[ 
    { 
     "_id" : "", 
     "value" : 3 
    }, 
    { 
     "_id" : "url1.com", 
     "value" : 6 
    }, 
    { 
     "_id" : "url2", 
     "value" : 1 
    } 
] 

很乾淨。請記住將refers替換爲您的收藏名稱:db.<collection>.mapReduce。你可以在這裏找到更多有關mapReduce的信息:http://docs.mongodb.org/manual/core/map-reduce/

+0

我不得不調整它(很多),讓它進入我的自定義框架(我使用查詢ervry其他地方,但在那裏),但這確實很好:) – DrakaSAN 2014-09-03 10:05:14

+0

偉大的:)很高興我能幫上忙.. – 2014-09-03 15:33:28

相關問題