2016-11-17 76 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']