MongoDB $数组项的总和

时间:2016-03-31 12:37:52

标签: mongodb python-2.7 pymongo

我正在为MongoDB提供一个机会,并使用MongoDB和PYTHON构建一个简单的日志。我有这个简单的结构:

db.posts.findOne()
{
"waketime": ISODate("2016-03-18T11:20:00Z"),
"bedtime": ISODate("2016-03-18T22:00:00Z"),
"day": "day entry",
"dream": "dream entry",
"workout" : [{"type":"cardio"},{"time":45}],
"meditation" : [{"time":10},{"time":10}],
"sex": "none"
}

我正在努力争取我花在锻炼上的时间以及每次锻炼所花费的时间。最后我得到了这个:

cursor = db.posts.aggregate([
    {"$group": {"_id" : "$workout.type", "count": {"$sum": "$workout.time"}}}
])

它返回:

{u'count': 0, u'_id': [u'cardio']}
{u'count': 0, u'_id': [u'strength']}

它似乎已在workout.type上正确分组,但它并不是$ sum workout.time

谁能帮帮我?

谢谢

1 个答案:

答案 0 :(得分:1)

Note that the field workout is a list of documents. Your error is that you're treating this field as a subdocument. You will be able to solve your problem changing the data model and keep your aggregation as it is. So, try the following model instead:

db.posts.findOne()
{
"waketime": ISODate("2016-03-18T11:20:00Z"),
"bedtime": ISODate("2016-03-18T22:00:00Z"),
"day": "day entry",
"dream": "dream entry",
"workout" : {
    "type":"cardio",
    "time":45
},
"meditation" : {
    "type":"dunno",
    "time":10
},
"sex": "none"
}

EDIT:

okay but what if i have multiple workouts a day ?

Good point. Let's say that my answer above solves the problem in a bad way because I'm adding the limitation of doing only one workout per day. Let's go back to your something like your model where this limitation doesn't exist. I've needed to amend it anyway in order to make all the items in the lists equivalent

db.posts.findOne()
{
"waketime": ISODate("2016-03-18T11:20:00Z"),
"bedtime": ISODate("2016-03-18T22:00:00Z"),
"day": "day entry",
"dream": "dream entry",
"workout" : [{"type":"cardio", "time":45},{"type": "strength", "time":45}],
"meditation" : [{"time":10},{"time":10}],
"sex": "none"
}

For this example you can use $unwind as one of the steps in your aggregation pipeline:

db.posts.aggregate([{$unwind:{"$workout"}},{$group:{_id:"$workout.type", count:{$sum:"$workout.time"}}}])

I haven't tested it, but I hope it works.

Regards