Курсор PyMongo batch_size - PullRequest
       3

Курсор PyMongo batch_size

0 голосов
/ 21 февраля 2019

В PyMongo 3.7.2 я пытаюсь прочитать коллекцию в виде фрагментов, используя batch_size для курсора MongoDB, как описано здесь .Основная идея заключается в использовании метода find () для объекта коллекции с параметром batch_size.Но что бы я ни пытался, курсор всегда возвращает все документы в моей коллекции.

Основной фрагмент моего кода выглядит следующим образом (в коллекции более 10 тыс. Документов):

import pymongo as pm

client = pm.MongoClient()
coll = client.get_database('db').get_collection('coll')

cur = coll.find({}, batch_size=500)

Однако,курсор всегда сразу возвращает полный размер коллекции.Я использую это, как описано в документации.

У кого-нибудь есть идеи, как правильно перебирать коллекцию партиями?Существуют способы зацикливания на выходе метода find (), но он все равно сначала получит полную коллекцию и будет зацикливаться только на уже извлеченных документах в памяти.Предполагается, что параметр batch_size позволяет получить пакет и выполнить обход данных каждый раз на сервере для экономии места в памяти.

1 Ответ

0 голосов
/ 22 февраля 2019

У Pymongo есть несколько помощников по качеству жизни для класса Cursor, поэтому он автоматически сделает за вас пакет и вернет вам результат с точки зрения документов.

Параметр batch_sizeустановлен, но идея в том, что вам нужно только установить его в методе find(), а не выполнять ручные низкоуровневые вызовы или перебирать партии.

Например, если у меня 100 документов вмоя коллекция:

> db.test.count()
100

Затем я задаю уровень профилирования , чтобы регистрировать все запросы:

> db.setProfilingLevel(0,-1)
{
  "was": 0,
  "slowms": 100,
  "sampleRate": 1,
  "ok": 1,
...

Затем я использую pymongo, чтобы указать batch_size из 10:

import pymongo
import bson

conn = pymongo.MongoClient()
cur = conn.test.test.find({}, {'txt':0}, batch_size=10)
print(list(cur))

Запустив этот запрос, я вижу в журнале MongoDB:

2019-02-22T15:03:54.522+1100 I COMMAND  [conn702] command test.test command: find { find: "test", filter: {} ....
2019-02-22T15:03:54.523+1100 I COMMAND  [conn702] command test.test command: getMore { getMore: 266777378048, collection: "test", batchSize: 10, .... 
(getMore repeated 9 more times)

Таким образом, запрос был получен с сервера в указанных пакетах.Это просто скрыто от вас через Cursor класс.

Редактировать

Если вам действительно нужно получить документы в пакетном режиме, естьфункция find_raw_batches() в разделе Коллекция ( ссылка на документ ).Этот метод работает аналогично find() и принимает те же параметры.Однако имейте в виду, что он вернет сырой BSON, который необходимо будет декодировать приложением на отдельном этапе.Примечательно, что этот метод не поддерживает сеансов .

Сказав, что, если целью является снижение использования памяти приложением, стоит рассмотреть возможность изменения запроса, чтобы вместо него использовались диапазоны.Например:

find({'$gte': <some criteria>, '$lte': <some other criteria>})

Запросы диапазона легче оптимизировать, могут использовать индексы и (на мой взгляд) легче отлаживать и легче перезапускать, если запрос прерывается.Это менее гибко при использовании пакетов, когда вам нужно перезапустить запрос с нуля и снова просмотреть все пакеты, если он будет прерван.

...