2016-02-22 3 views
3

У меня возникли проблемы с очень большой коллекцией MongoDB (19 миллионов документов).Почему данные отсутствуют при обработке больших коллекций MongoDB в PyMongo? Что я могу сделать с этим?

Когда я просто перебираю коллекцию, как показано ниже, PyMongo, похоже, сдаётся после 10 593 454 документов. Это похоже на то же, даже если я использую skip(), вторая половина коллекции кажется программно недоступной.

#!/usr/bin/env python 
import pymongo 

client = pymongo.MongoClient() 
db = client['mydb'] 
classification_collection = db["my_classifications"] 

print "Collection contains %s documents." % db.command("collstats", "my_classifications")["count"] 

for ii, classification in enumerate(classification_collection.find(no_cursor_timeout=True)): 
    print "%s: created at %s" % (ii,classification["created_at"]) 

print "Done." 

Отчеты сценарий изначально:

Collection contains 19036976 documents. 

В конце концов, сценарий завершается, я не получаю никаких ошибок, и я получаю "Done". сообщение. Но последняя строка Печатаемая

10593454: created at 2013-12-12 02:17:35 

Все мои записи вошли в систему только в течение последних 2-х лет, самые последние из них, кажется, недоступны. Кто-нибудь знает, что здесь происходит? Что я могу сделать по этому поводу?

+0

как долго он настраивается, прежде чем он «кончится». Может ли это время? – Takarii

+0

@Takarii, как вы можете видеть, я отключил таймауты, используя 'no_cursor_timeout = True'. Сказав это, он вечно вешает на эту сумму 10 593 454. Таким образом, это действительно похоже на тайм-аут. хотя программа в конечном итоге продолжается. Но почему каждый тайм-аут после такой же конкретной записи? – alexbfree

+0

Не слишком уверен. Можете ли вы напрямую запросить базу данных, чтобы узнать, действительно ли вы можете получить записи в первую очередь? – Takarii

ответ

1

ОК хорошо благодаря this helpful article Я нашел другой способ распечатать документы, которые, похоже, не подвержены этой проблеме «недостающих данных»/«таймаута». По существу, вы должны использовать find() и limit() и полагаться на натуральный заказ _id вашей коллекции, чтобы получить документ на страницах. Вот мой пересмотренный код:

#!/usr/bin/env python 
import pymongo 

client = pymongo.MongoClient() 
db = client['mydb'] 
classification_collection = db["my_classifications"] 

print "Collection contains %s documents." % db.command("collstats", "my_classifications")["count"] 

# get first ID 
pageSize = 100000 
first_classification = classification_collection.find_one() 
completed_page_rows=1 
last_id = first_classification["_id"] 

# get the next page of documents (read-ahead programming style) 
next_results = classification_collection.find({"_id":{"$gt":last_id}},{"created_at":1},no_cursor_timeout=True).limit(pageSize) 

# keep getting pages until there are no more 
while next_results.count()>0: 
    for ii, classification in enumerate(next_results): 
    completed_page_rows+=1 
    if completed_page_rows % pageSize == 0: 
     print "%s (id = %s): created at %s" % (completed_page_rows,classification["_id"],classification["created_at"]) 
    last_id = classification["_id"] 
    next_results = classification_collection.find({"_id":{"$gt":last_id}},{"created_at":1},no_cursor_timeout=True).limit(pageSize) 

print "\nDone.\n" 

Надеюсь, что, написав это решение, это поможет другим, кто столкнулся с этой проблемой.

Примечание: в этом обновленном листинге также приводятся предложения @Takarii и @ adam-comerford в комментариях, теперь я получаю только поля, которые мне нужны (_id по умолчанию), и я также распечатываю идентификаторы для справки ,