pymongo由于异常而失败:聚合结果超出了最大文档大小

时间:2014-03-26 14:42:54

标签: python mongodb aggregation-framework pymongo

这是我的功能

def get_db_data(codes, collection, projection_list):
  try:
    project = {'$project': dict(map(lambda x: (x.replace('.','_'),'$%s'%x), projection_list),_id=0, code=1)}
    db_data = db[collection].aggregate([{'$match': {'code':{'$in':codes}}}, project])
    return dict( map(lambda x: (x.get('code'), x), db_data['result']) )
  except IndexError:
    return {}

这里projection_list是

['fundamental.current_ratio', 'ebscore.latest_year.rating', 'pro_valuation.result', 
 'company_profile.profile', 'fundamental.yield', 'intelliquants.observation_period', 
 'fundamental.roa', 'fundamental.roe', 'pro_valuation.percentage_diff',
 'fundamental.tpftotalpromoter.S','intelliquants.avg_returns', 'fundamental.tptotalpublic.S',
 'fundamental.ttmnp', 'fundamental.reported_eps', 'Nicdata.description', 'fundamental.ttmeps',
 'fundamental.roce', 'pro_technical.result', 'ebscore.latest_year.result', 'company_equity.mcap',
 'fundamental.total_debt_equity', 'intelliquants.highest_monthly_returns', 'intelliquants.percentage_positive',
 'fundamental.pat_margin', 'fundamental.pshftotalpromoter.S', 'ebscore.latest_year.rationale', 
 'pro_valuation.final_value', 'intelliquants.worst_monthly_returns']

我知道聚合调用的完整结果不能大于16 MB。

我如何使用map reduce函数或mongodb中的任何其他函数执行此操作。我希望聚合函数返回的格式相同。

1 个答案:

答案 0 :(得分:0)

如果问题是集合的大小太大,一个选项是使用skip关键字和循环来返回集合子集上的较小文档,然后自己将它们合并在一起。所以,举个例子,这是我最近处理的一个例子:

def cross_query(collection, id_list, start_date, end_date, limit, skip):
    results = collection.aggregate([
        { "$match" : stuff}, 
        { "$group" : stuff},
        { "$unwind": stuff},
        { "$group" : stuff},
        { "$sort": stuff},
        { "$skip" : skip },
        { "$limit": limit}
    ])
    return results["result"]

def query(collection, id_list, start_date, end_date, limit):
    over = limit % 250000
    combined_results = []
    for i in range(limit / 250000):
        combined_results += cross_query(collection, id_list, start_date, end_date, 250000, 250000 * i))

    if over:
        combined_results += cross_query(collection, id_list, start_date, end_date, over, (limit / 250000) * 250000))

    return combined_results

所以这需要一个限制,比如850000,并继续返回第一个250000结果,然后是下一个250000,然后是下一个250000,然后是最后的100000.对于每个结果的大小,250000标记舒适地适合16mb