Класс 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 __construct()
final public getId(): MongoDB\BSON\Int64
final public isDead(): bool
public key(): int
public next(): void
public rewind(): void
final public setTypeMap(array $typemap): void
final public toArray(): array
public 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.

Содержание