2012-08-15 112 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