2012-08-15 114 views
1

我有一個python腳本女巫我用來將大集合聚集成小塊,並按時間戳分組。MongoDB MapReduce,日期和%運算符

map = Code("function(number) {" 
    "emit({" 
     "ts : new Date(new Date((this.ts - (this.ts % (60 * number))) * 1000).setSeconds(0))" 
    "}, 1);" 
"}") 

reduce = Code("function(key, vals) {" 
    "var sum = 0;" 
    "for (var i in vals) {" 
     "sum += vals[i]" 
    "}" 
    "return sum;" 
"}") 

正如你所看到的,這是一個非常簡單的MapReduce和時間戳(TS)應分鐘的ANNY給定數量進行分組。我已經測試了這裏的Javascript http://jsfiddle.net/QgMzK/1/,它似乎工作正常。但是,當我在Python中運行它時,所有時間戳都變成ISODate(「1970-01-01T00:00:00Z」)。

任何想法?

回答

3

你的地圖功能需要一個參數:number,其中,當被稱爲地圖,減少,將被設置爲null,coertion(和一些%零)會使日後的地圖將返回ISODate("0NaN-NaN-NaNTNaN:NaN:NaNZ")。這種類型轉換後變成datetime.datetime(1970, 1, 1, 0, 0)

刪除參數,它應該工作。

編輯

要確認,嘗試運行這段代碼:

from pymongo import Connection 
from bson.code import Code 

db = Connection().mr_test 
for i in xrange(10): 
    db.things.insert({"x" : i}) 


map = Code("function(number) {" 
    "emit({" 
     "ts : number" 
    "}, 1);" 
"}") 

reduce = Code("function(key, vals) {" 
    "var sum = 0;" 
    "for (var i in vals) {" 
     "sum += vals[i]" 
    "}" 
    "return sum;" 
"}") 


result = db.things.map_reduce(map, reduce, "test_results") 
for doc in result.find(): 
    print doc 

我的機器上的結果是:

{u'_id': {u'ts': None}, u'value': 10.0} 

注意ts是結果None,導致number在執行映射功能時未設置。

編輯2

AFAIK一個參數傳遞給map的唯一途徑是通過在map_reduce使用scope可選參數,但隨後你就必須從無論如何圖簽名刪除。

因此,通過改變你的地圖:

map = Code("function() {" 
    "emit({" 
     "ts : new Date(new Date((this.ts - (this.ts % (60 * number))) * 1000).setSeconds(0))" 
    "}, 1);" 
"}") 

,並通過調用:

db.whatever.map_reduce(map, reduce, "collection_name", scope = {"number" : the_value_your_function_needs}) 

你可以得到你想要的結果。

+0

地圖功能的編號參數使我能夠按最近的5,10或X分鐘對收藏進行分組。如果我將ts-prop更改爲ex,ts:number: – 2012-08-15 11:16:51

+0

@Jarsäter,這個參數很好奇,因爲我可以看到它返回'None'作爲map-reduce結果中的唯一鍵,並且它完全一致與我的答案。 – soulcheck 2012-08-15 11:45:07