使用mongo聚合框架聚合映射键

时间:2015-08-07 15:07:37

标签: python arrays mongodb mongodb-query pymongo

我有一个用例,我将文档存储在mongo集合中,其中一列作为map。例如:

{ "_id" : ObjectId("axa"), "date" : "2015-08-05", "key1" : "abc",  "aggregates" : { "x" : 12, "y" : 1 } }

{ "_id" : ObjectId("axa1"), "date" : "2015-08-04", "key1" : "abc",  "aggregates" : { "x" : 4, "y" : 19 } }

{ "_id" : ObjectId("axa2"), "date" : "2015-08-03", "key1" : "abc",  "aggregates" : { "x" : 3, "y" : 13 } }

需要注意的一点是聚合子文档中的键可能会发生变化。例如,代替x和y,它可以是z和k或任何组合和任何数字

现在我从API中提取数据,需要使用mongo聚合框架来聚合日期范围。例如,对于上面的示例,我想运行日期08/03 -08/05的查询并聚合x和y(按x和y分组),结果应为

 {  "key1" : "abc",  "aggregates" : { "x" : 19, "y" : 33 } }

我该怎么做?

1 个答案:

答案 0 :(得分:0)

首先,您应该更新文档,因为date是字符串。您可以使用Bulk() API

执行此操作
from datetime import datetime

import pymongo

conn = pymongo.MongoClient()
db = conn.test
col = db.collection

bulk = col.initialize_ordered_bulk_op()
count = 0

for doc in col.find():
    conv_date = datetime.strptime(doc['date'], '%Y-%m-%d')
    bulk.find({'_id': doc['_id']}).update_one({'$set': {'date': conv_date}})
    count = count + 1
    if count % 500 == 0:
        # Execute per 500 operations and re-init.
        bulk.execute()
        bulk = col.initialize_ordered_bulk_op()

# Clean up queues
if count % 500 != 0:
    bulk.execute()

然后是聚合部分:

您需要使用$match运算符按date过滤文档。按指定的标识key1下一步$group您的文档并应用累加器$sum。使用$project,您可以重塑文档。

x = 'x'
y = 'y'

col.aggregate([
    {'$match': { 'date': { '$lte': datetime(2015, 8, 5), '$gte': datetime(2015, 8, 3)}}}, 
    {'$group': {'_id': '$key1', 'x': {'$sum': '$aggregates. ' +x}, 'y': {'$sum': '$aggregates.' + y}}},
    {'$project': {'key1': '$_id', 'aggregates': {'x': '$x', 'y': '$y'}, '_id': 0}} 
])