2013-06-18 25 views
0

我有一个数组存储在mongo数据库中的每个文档/记录中,我需要为该数组中的每个元素计算一个分数,并将数值通过数组元素中的另一个字段聚合。整个数组在Mongo中记录聚合

我很难解释我想用英文做什么,所以这里是我期待做的python示例。

records = [ 
    {"state": "a", "initvalue": 1, "data": [{"time": 1, "value": 2}, {"time": 2, "value": 4}]}, 
    {"state": "a", "initvalue": 5, "data": [{"time": 1, "value": 7}, {"time": 2, "value": 9}]}, 
    {"state": "b", "initvalue": 4, "data": [{"time": 1, "value": 2}, {"time": 2, "value": 1}]}, 
    {"state": "b", "initvalue": 5, "data": [{"time": 1, "value": 3}, {"time": 2, "value": 2}]} 
] 


def sign(record): 
    return 1 if record["state"] == "a" else -1 


def score(record): 
    return [{"time": element["time"], "score": sign(record) * (element["value"] - record["initvalue"])} for element in record["data"]] 

scores = [] 
for record in records: 
    scores += score(record) 

sums = {} 
for score in scores: 
    if score["time"] not in sums: 
     sums[score["time"]] = 0 
    sums[score["time"]] += score["score"] 

print '{:>4} {:>5}'.format('time', 'score') 
for time, value in sums.iteritems(): 
    print '{:>4} {:>5}'.format(time, value) 

此计算用于状态a和用于状态b略微不同的得分函数,然后聚集在每个时间条目的分数。

这里是

time score 
    1  7 
    2 13 

我试图找出如何做到这一点的蒙戈,不拉记录到Python和重塑聚集的结果。

感谢您的帮助!

回答

0

好的。我明白了这一点。一旦我真正理解了管道的工作和关于条件功能的一切是如何结合在一起的。

from pymongo import MongoClient 
client = MongoClient() 
result = client.mydb.foo.aggregate([ 
    {'$project': {'_id': 0, 'data': 1, 'initvalue': 1, 'state': 1}}, 
    {'$unwind': '$data'}, 
    {'$project': { 
     'time': '$data.time', 
     'score': {'$multiply': [ 
      {'$cond':  [{'$eq': ['$state', 'a']}, 1, -1]}, 
      {'$subtract': ['$data.value', '$initvalue']} 
     ]} 
    }}, 
    {'$group': { 
     '_id': '$time', 
     'score': {'$sum': '$score'} 
    }}, 
    {'$project': {'_id': 0, 'time': '$_id', 'score': 1}} 
]) 
for record in result['result']: 
    print record 

这就产生期望的结果

{u'score': 13, u'time': 2} 
{u'score': 7, u'time': 1} 
+0

如果你无法理解上面的命令,这可能帮助。聚合函数是一个数组(“管道”)的命令。尝试从数组末尾移除命令并查看中间结果如何更改。 – Jon