2016-11-17 54 views
0

我试图查询一个MongoDB数据库并将两组结果('_id'和'Team')放入两个单独的列表中。List Comprehension返回空列表

import pymongo 

client = pymongo.MongoClient('localhost:27017') 
db = client['db_name'] 

query = {'Team': {'$exists': 1}} 
projection = {'_id': 1, 'Team': 1} 

data = db['collection_name'].find(query, projection) # line 9 

id_list = [value for dict in data for key, value in dict.iteritems() if key == '_id'] 
teams_list = [value for dict in data for key, value in dict.iteritems() if key == 'Team'] 

print id_list 
print teams_list 

client.close() 

对于上面的代码,'id_list'是预期的,但'teams_list'是空的。当我在'id_list'之前放置'teams_list'时,我得到预期的'teams_list'输出,'id_list'是空的。当我在两个列表解析之间重复数据调用(第9行)时,我得到了两个列表的预期输出。

任何想法为什么会发生这种情况?

+4

据推测,'找到()'返回生成器,当你迭代它时会被消耗掉。 –

+0

您需要将'data'定义为:'data = list(db ['collection_name']。find(query,projection))''。注意:'list(...)' –

回答

1

您需要定义您的data为:

data = list(db['collection_name'].find(query, projection)) 

由于find()回报发电机。一旦你迭代了这些值,那些值就会丢失。您需要将它们存储为list。这里list()这样做,即将由发生器返回的项目存储为列表。

相反迭代名单的两倍,更好的办法将是两个做单回路为:

id_list, teams_list = [], [] 

# v `dict` is in-built data type, you should not be using it as variable 
for d in data: 
    for key, value in d.iteritems(): 
     if key == '_id': 
      id_list.append(value) 
     elif key == 'Team': 
      teams_list.append(value) 

参考Generator wiki针对与发电机

+0

这工作完全谢谢你。我怎么知道find()返回一个生成器 - 在MongoDB中,我相信他们把它称为一个游标......是这样吗? –

+0

查看与发生器相关的文档:https://wiki.python.org/moin/Generators –

0

更多信息如前所述罪魁祸首这里是find()方法,它将返回一个Cursor对象,该对象在第一次迭代时将被消耗。

但是您正在使用错误的方法进行这项工作。您需要使用.aggregate()方法。

query = {'Team': {'$exists': 1}} 

cursor = db['collection_name'].aggregate([ 
    {'$match': query } 
    { '$group': { 
     '_id': None, 
     'id_list': {'$push': '$_id'}, 
     'teams_list': {'$push': '$Team'} 
    }} 
]) 

.aggregate()方法,就像他在犯罪的合作伙伴.find()在结果集,它是一个发电机状物体返回CommandCursor

因为我们被None分组,迭代光标将产生一个单一的文件,这意味着你可以安全地完成:

print list(cursor)[0] # return a dictionary 

result = list(cursor)[0] 
print result['id_list'] 
print result['teams_list']