(mongodb >=1.0.0)
Класс MongoDB\Driver\Cursor содержит результаты команды MongoDB command или запроса и может быть возвращен MongoDB\Driver\Manager::executeCommand() или MongoDB\Driver\Manager::executeQuery() соответственно.
Версия | Описание |
---|---|
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 and » 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. Эта итерация может вызвать следующие исключения: