Как прочитать коллекцию кусками по 1000? - PullRequest
9 голосов
/ 20 марта 2012

Мне нужно прочитать всю коллекцию из MongoDB (имя коллекции «test») в коде Python.Я пытался, как

    self.__connection__ = Connection('localhost',27017)
    dbh = self.__connection__['test_db']            
    collection = dbh['test']

Как прочитать коллекцию по частям на 1000 (чтобы избежать переполнения памяти, потому что коллекция может быть очень большой)?

Ответы [ 4 ]

6 голосов
/ 20 марта 2012

Я согласен с Ремоном, но вы упомянули партии по 1000, которые его ответ на самом деле не охватывает.Вы можете установить размер пакета на курсоре:

cursor.batch_size(1000);

Вы также можете пропустить записи, например:

cursor.skip(4000);

Это то, что вы ищете?Это эффективно шаблон пагинации.Однако, если вы просто пытаетесь избежать исчерпания памяти, вам не нужно устанавливать размер пакета или пропускать.

5 голосов
/ 20 марта 2012

Используйте курсоры.Курсоры имеют переменную «batchSize», которая контролирует, сколько документов фактически отправляется клиенту за пакет после выполнения запроса.Вам не нужно трогать этот параметр, так как по умолчанию все в порядке, а сложность, если вызов команд getmore скрыт от вас в большинстве драйверов.Я не знаком с пимонго, но он работает так:

cursor = db.col.find() // Get everything!

while(cursor.hasNext()) {
    /* This will use the documents already fetched and if it runs out of documents in it's local batch it will fetch another X of them from the server (where X is batchSize). */
    document = cursor.next();

    // Do your magic here
}
3 голосов
/ 20 января 2019

вдохновленный @Rafael Valero + исправление последней ошибки чанка в его коде и придание ей более общего характера. Я создал функцию генератора для итерации по коллекции монго с запросом и проекцией:

def iterate_by_chunks(collection, chunksize=1, start_from=0, query={}, projection={}):
   chunks = range(start_from, collection.find(query).count(), int(chunksize))
   num_chunks = len(chunks)
   for i in range(1,num_chunks+1):
      if i < num_chunks:
          yield collection.find(query, projection=projection)[chunks[i-1]:chunks[i]]
      else:
          yield collection.find(query, projection=projection)[chunks[i-1]:chunks.stop]

, например, сначала вы создаетеитератор, подобный следующему:

mess_chunk_iter = iterate_by_chunks(db_local.conversation_messages, 200, 0, query={}, projection=projection)

, а затем итерация по частям:

chunk_n=0
total_docs=0
for docs in mess_chunk_iter:
   chunk_n=chunk_n+1        
   chunk_len = 0
   for d in docs:
      chunk_len=chunk_len+1
      total_docs=total_docs+1
   print(f'chunk #: {chunk_n}, chunk_len: {chunk_len}')
print("total docs iterated: ", total_docs)

chunk #: 1, chunk_len: 400
chunk #: 2, chunk_len: 400
chunk #: 3, chunk_len: 400
chunk #: 4, chunk_len: 400
chunk #: 5, chunk_len: 400
chunk #: 6, chunk_len: 400
chunk #: 7, chunk_len: 281
total docs iterated:  2681
0 голосов
/ 06 марта 2018

Для создания начального соединения в настоящее время в Python 2 используется Pymongo:

host = 'localhost'
port = 27017
db_name = 'test_db'
collection_name = 'test'

Для подключения используется MongoClient

# Connect to MongoDB
client = MongoClient(host=host, port=port)
# Make a query to the specific DB and Collection
dbh = client[dbname]
collection = dbh[collection_name]

Так что отсюда правильный ответ. Я хочу читать, используя чанки (в данном случае размер 1000).

chunksize = 1000

Например, мы можем решить, сколько чанков размера (размер чанка) мы хотим.

# Some variables to create the chunks
skips_variable = range(0, db_aux[collection].find(query).count(), int(chunksize))
if len(skips_variable)<=1:
    skips_variable = [0,len(skips_variable)]

Затем мы можем извлечь каждый кусок.

for i in range(1,len(skips_variable)):

    # Expand the cursor and retrieve data 

    data_from_chunk = dbh[collection_name].find(query)[skips_variable[i-1]:skips_variable[i]]))

Где запрос в этом случае query = {}.

Здесь Я использую аналогичные идеи для создания фреймов данных из MongoDB, Здесь Я использую что-то подобное для записи в MongoDB кусками.

Надеюсь, это поможет.

...