# Класс MongoDB\Driver\Cursor

(mongodb >=1.0.0)

## Введение

Класс MongoDB\Driver\Cursor содержит результаты команды MongoDB command или запроса и может быть возвращён MongoDB\Driver\Manager::executeCommand() или MongoDB\Driver\Manager::executeQuery() соответственно.

## Обзор класса

final class MongoDB\Driver\Cursor implements MongoDB\Driver\CursorInterface {
/* Методы */
final private function __construct()
public function current(): array|object|null
final public function getId(): MongoDB\BSON\Int64
final public function getServer(): MongoDB\Driver\Server
final public function isDead(): bool
public function key(): int
public function next(): void
public function rewind(): void
final public function setTypeMap(array `$typemap`): void
final public function toArray(): array
public function valid(): bool
}

## Список изменений

Версия | Описание
--- | ---
PECL-модуль mongodb 1.9.0 | Класс теперь реализует интерфейс Iterator.
PECL-модуль mongodb 1.6.0 | Класс теперь реализует интерфейс MongoDB\Driver\CursorInterface, который наследует Traversable.

## Примеры

Пример #1 Reading a result set

Методы MongoDB\Driver\Manager::executeCommand() и MongoDB\Driver\Manager::executeQuery() возвращают результаты в виде объекта MongoDB\Driver\Cursor.

Поскольку класс MongoDB\Driver\Cursor реализует интерфейс Traversable, программистам доступна итерация по набору результата конструкцией `foreach`.

    <?php

    $manager = new MongoDB\Driver\Manager();

    /* Вставить определённые документы, чтобы наш запрос вернул результаты */
    $bulkWrite = new MongoDB\Driver\BulkWrite;
    $bulkWrite->insert(['name' => 'Ceres', 'size' => 946, 'distance' => 2.766]);
    $bulkWrite->insert(['name' => 'Vesta', 'size' => 525, 'distance' => 2.362]);
    $manager->executeBulkWrite("test.asteroids", $bulkWrite);

    /* Запрос на получение всех элементов в коллекции */
    $query = new MongoDB\Driver\Query( [] );

    /* Запрос коллекции "asteroids" базы данных "test" */
    $cursor = $manager->executeQuery("test.asteroids", $query);

    /* Теперь $cursor содержит объект, обёрнутый вокруг набора с результатом. Используйте
     * foreach() для итеации по всему результату */
    foreach ($cursor as $document) {
        print_r($document);
    }

    ?>

Вывод приведённого примера будет похож на:

    stdClass Object
    (
        [_id] => MongoDB\BSON\ObjectId Object
            (
                [oid] => 5a4cff2f122d3321565d8cc2
            )

        [name] => Ceres
        [size] => 946
        [distance] => 2.766
    )
    stdClass Object
    (
        [_id] => MongoDB\BSON\ObjectId Object
            (
                [oid] => 5a4cff2f122d3321565d8cc3
            )

        [name] => Vesta
        [size] => 525
        [distance] => 2.362
    )

Пример #2 Чтение набора результатов для хвостового курсора

» Хвостовые курсоры — особый тип курсора СУБД MongoDB, который разрешает клиенту читать отдельные результаты, а затем ждать, пока не появятся дополнительные документы. Эти курсоры часто используются с » Capped Collections и » Change Streams.

Хотя стандартные курсоры возможно перебрать конструкцией `foreach` один раз, этот подход не сработает с хвостовыми курсорами. Цикл останавливается по достижении конца начального набора результатов, когда хвостовой курсор перебирают конструкцией `foreach`. Попытка продолжить итерацию курсора со вторым `foreach` выбросить исключение, поскольку PHP пытается перемотать курсор. Подобно объектам результатов в других драйверах баз данных, курсоры в СУБД MongoDB поддерживают только продвижение вперёд, поэтому их нельзя перемотать.

Для непрерывного считывания с хвостового курсора объект курсора заворачивают в объект IteratorIterator. Это разрешает приложению напрямую управлять итерацией курсора, избегать непреднамеренного перемотки курсора и решать, когда ждать новых результатов или прекратить итерацию.

Продемонстрируем хвостовой курсор в действии, для этого напишем два скрипта: «производитель» (producer) и «потребитель» (consumer). Скрипт продюсера создаст новую capped-коллекцию командой » create и начнёт вставку нового документа в эту коллекцию каждую секунду.

    <?php

    $manager = new MongoDB\Driver\Manager;

    $manager->executeCommand('test', new MongoDB\Driver\Command([
        'create' => 'asteroids',
        'capped' => true,
        'size' => 1048576,
    ]));

    while (true) {
        $bulkWrite = new MongoDB\Driver\BulkWrite;
        $bulkWrite->insert(['createdAt' => new MongoDB\BSON\UTCDateTime]);
        $manager->executeBulkWrite('test.asteroids', $bulkWrite);

        sleep(1);
    }

    ?>

Пока скрипт продюсера (producer) запущен, выполняют второй пользовательский скрипт для чтения вставленных документов с помощью хвостового (tailable) курсора, обозначенного параметрами `tailable` и `awaitData` в методе MongoDB\Driver\Query::__construct().

    <?php

    $manager = new MongoDB\Driver\Manager;

    $query = new MongoDB\Driver\Query([], [
        'tailable' => true,
        'awaitData' => true,
    ]);

    $cursor = $manager->executeQuery('test.asteroids', $query);

    $iterator = new IteratorIterator($cursor);

    $iterator->rewind();

    while (true) {
        if ($iterator->valid()) {
            $document = $iterator->current();
            printf("Пользовательский документ создан: %s\n", $document->createdAt);
        }

        $iterator->next();
    }

    ?>

Пользовательский скрипт начнёт с быстрой печати всех доступных документов в заблокированной коллекции, как если бы коллекцию перебирали конструкцией `foreach`; но при достижении конца начального набора результатов перебор не завершится. Поскольку курсор хвостовой, вызов метода IteratorIterator::valid() будет блокировать и ждать дополнительных результатов. Метод IteratorIterator::valid() также используется для проверки наличия на каждом этапе данных, доступных для чтения.

> Замечание: В этом примере используется опция запроса `awaitData`, чтобы проинструктировать сервер блокировать в течение короткого периода (например, одну секунду) в конце набора результатов перед возвратом ответа драйверу. Это используется для предотвращения агрессивного опроса (polling) сервера при отсутствии результатов. Параметр `maxAwaitTimeMS` может использоваться в сочетании с `tailable` и `awaitData`, чтобы указать время, которое сервер должен блокировать, когда он достигнет конца набора результатов.

## Ошибки

При итерации по объекту курсора BSON-данные преобразовываются в PHP-переменные. Эта итерация иногда вызывает следующие исключения:

- Выбрасывает исключение MongoDB\Driver\Exception\InvalidArgumentException, если невозможно создать класс на карте типов или класс не реализует интерфейс MongoDB\BSON\Unserializable.
- Метод выбрасывает исключение MongoDB\Driver\Exception\UnexpectedValueException, если во входных данных передали больше одного BSON-документа. Возможные причины включают, но не ограничиваются недопустимым BSON-форматом, лишними данными или неожиданной ошибкой » libbson.

## Содержание

- MongoDB\Driver\Cursor::__construct — Создаёт новый объект Cursor (не используется)
- MongoDB\Driver\Cursor::current — Возвращает текущий элемент
- MongoDB\Driver\Cursor::getId — Возвращает идентификатор текущего курсора
- MongoDB\Driver\Cursor::getServer — Возвращает сервер, связанный с курсором
- MongoDB\Driver\Cursor::isDead — Проверяет, исчерпан ли курсор или может содержать дополнительные результаты
- MongoDB\Driver\Cursor::key — Возвращает индекс текущего результата в курсоре
- MongoDB\Driver\Cursor::next — Перемещает курсор на следующий результат
- MongoDB\Driver\Cursor::rewind — Перемещает курсор к первому результату
- MongoDB\Driver\Cursor::setTypeMap — Устанавливает карту типа для десериализации BSON
- MongoDB\Driver\Cursor::toArray — Возвращает массив, содержащий все результаты курсора
- MongoDB\Driver\Cursor::valid — Проверяет, корректна ли текущая позиция курсора

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open