Подтвердить что ты не робот

PyMongo - итерация курсора

Недавно я начал тестировать MongoDB через оболочку и через PyMongo. Я заметил, что, возвращая курсор и пытающийся перебрать его, кажется, узкое место в фактической итерации. Есть ли способ вернуть более одного документа во время итерации?

Псевдокод:

for line in file:
    value = line[a:b]
    cursor = collection.find({"field": value})
    for entry in cursor:
        (deal with single entry each time)

То, что я надеюсь сделать, это примерно так:

for line in file
    value = line[a:b]
    cursor = collection.find({"field": value})
    for all_entries in cursor:
        (deal with all entries at once rather than iterate each time)

Я пробовал использовать batch_size() в соответствии с этим вопросом и изменяя значение до 1000000, но он, похоже, не имеет никакого эффекта (или я делаю это неправильно).

Любая помощь приветствуется. Пожалуйста, будьте спокойны в этом новичке Mongo!

--- EDIT ---

Спасибо, Калеб. Я думаю, вы указали, что я действительно пытался спросить, что это такое: есть ли способ сделать команду типа collection.findAll() или, может быть, cursor.fetchAll(), как есть с модулем cx_Oracle? Проблема заключается не в хранении данных, а в извлечении из Mongo DB как можно быстрее.

Насколько я могу судить, скорость, с которой мне возвращаются данные, продиктована моей сетью, так как Mongo должен однократно выбирать каждую запись, исправить?

4b9b3361

Ответ 1

Рассматривали ли вы такой подход, как:

for line in file
  value = line[a:b]
  cursor = collection.find({"field": value})
  entries = cursor[:] # or pull them out with a loop or comprehension -- just get all the docs
  # then process entries as a list, either singly or in batch

Альтернативно, что-то вроде:

# same loop start
  entries[value] = cursor[:]
# after the loop, all the cursors are out of scope and closed
for value in entries:
  # process entries[value], either singly or in batch

В принципе, до тех пор, пока у вас достаточно ОЗУ для хранения наборов результатов, вы должны убрать их с курсоров и удерживать их перед обработкой. Это вряд ли будет значительно быстрее, но оно смягчит любое замедление в отношении курсоров и позволит вам обрабатывать ваши данные параллельно, если вы настроены для этого.

Ответ 2

Вы также можете попробовать:

results = list(collection.find({'field':value}))

Это должно загрузить все прямо в ОЗУ.

Или это возможно, если ваш file не слишком большой:

values = list()
for line in file:
    values.append(line[a:b])
results = list(collection.find({'field': {'$in': values}}))

Ответ 3

toArray() может быть решением. Основываясь на документах, он сначала выполняет итерацию по всем курсорам на Mongo и только возвращает результаты один раз в виде массива.

http://docs.mongodb.org/manual/reference/method/cursor.toArray/

Это не похоже на list(coll.find()) или [doc for doc in coll.find()], которые извлекают один документ на Python за один раз и возвращаются к Mongo и выбирают следующий курсор.

Однако этот метод не был реализован на pyMongo... странный

Ответ 4

Как упоминалось выше @jmelesky, я всегда придерживаюсь такого же метода. Вот мой пример кода. Для хранения моего курсора twts_result, объявляющего список ниже для копирования. Используйте RAM, если вы можете хранить данные. Это решит проблему тайм-аут курсора, если никакая обработка и обновление не потребуются над вашей коллекцией, откуда вы выбрали данные.

Здесь я получаю твиты из коллекции.

twts_result = maindb.economy_geolocation.find({}, {'_id' : False})
print "Tweets for processing -> %d" %(twts_result.count())

tweets_sentiment = []
batch_tweets = []
#Copy the cursor data into list
tweets_collection = list(twts_result[:])
for twt in tweets_collection:
    #do stuff here with **twt** data