2013-06-18 53 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