» Cursores adaptáveis
são um tipo especial de cursor no MongoDB que permite ao cliente ler alguns
resultados e então esperar até que mais documentos fiquem disponíveis. Esses cursores
são usado principalmente com
» Coleções Limitadas
e » Fluxos de Alterações.
Enquanto os cursores normais podem ser iterados com foreach,
esse método não irá funcionar com cursores adaptáveis. Quando
foreach é usado com um cursor adaptável, a repetição irá
terminar quando alcançar o final do conjunto de resultados inicial. A tentativa de
continuar a iteração no cursor com um segundo
foreach lançaria uma exceção, já que o PHP tentaria
retroceder o cursor. De forma similar aos objetos de resultados em outros drivers de bancos de dados,
os cursores no MongoDB suportam apenas iteração para a frente, ou seja, eles não podem
ser retrocedidos.
Para ler continuamente a partir de um cursor adaptável, o objeto Cursor
deve ser encapsulado com um IteratorIterator. Isso
permite que a aplicação controle diretamente a iteração do cursor, evite
retroceder inadvertidamente o cursor e decida quando esperar por novos resultados
ou interromper totalmente a iteração.
Para demonstrar um cursor adaptável em ação, serão utilizados dois
scripts: um "produtor" e um "consumidor". O script produtor criará uma nova
coleção limitada usando o
comando » create
e procederá à inserção de um novo documento nessa coleção a cada segundo.
<?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);
}
?>
Com o script produtor ainda em execução, um segundo script consumidor pode ser
executado para ler os documentos inseridos usando um cursor adaptável, indicado
pelas opções tailable e awaitData
para o método 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("Documento consumido criado em: %s\n", $document->createdAt);
}
$iterator->next();
}
?>
O script consumidor começará mostrando rapidamente todos os documentos disponíveis
na coleção limitada (como se foreach tivesse sido usado);
entretanto, ele não terminará ao atingir o final do conjunto de resultados inicial.
Como o cursor pode ser seguido, chamar
IteratorIterator::next() bloqueará e aguardará
resultados adicionais. IteratorIterator::valid() também é
usado para verificar se realmente há dados disponíveis para leitura em cada etapa.