(mongodb >=1.0.0)
A classe MongoDB\Driver\Cursor encapsula os resultados de um comando ou consulta MongoDB e podem ser retornados por MongoDB\Driver\Manager::executeCommand() ou MongoDB\Driver\Manager::executeQuery(), respectivamente.
Versão | Descrição |
---|---|
PECL mongodb 1.9.0 | Implementa Iterator. |
PECL mongodb 1.6.0 | Implementa MongoDB\Driver\CursorInterface, que estende Traversable. |
Exemplo #1 Lendo um conjunto de resultados
MongoDB\Driver\Manager::executeCommand() e MongoDB\Driver\Manager::executeQuery() ambos retornam seus resultados como um objeto MongoDB\Driver\Cursor. Este objeto pode ser usado para iterar sobre conjunto de resultados do comando ou consulta.
Como MongoDB\Driver\Cursor implementa a
interface Traversable, pode-se simplesmente
iterar pelo conjunto de resultados com
foreach
.
<?php
$manager = new MongoDB\Driver\Manager();
/* Insere alguns documentos para que a consulta retorne informação */
$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);
/* Consulta todos os itens na coleção */
$query = new MongoDB\Driver\Query( [] );
/* Consulta a coleção "asteroids" do banco de dados "test" */
$cursor = $manager->executeQuery("test.asteroids", $query);
/* $cursor agora contém um objeto que envolve o conjunto de resultados. Pode-se
* usar foreach() para iterar por todo o resultado */
foreach($cursor as $document) {
print_r($document);
}
?>
O exemplo acima produzirá algo semelhante a:
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 }
Exemplo #2 Reading a result set for a tailable cursor
» Cursores adaptáveis são um tipo especial de cursor no MongoDB que permite ao cliente ler alguns resultado 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.
Nota: Este exemplo usa a opção de consulta
awaitData
para instruir o servidor a bloquear por um curto período (por exemplo, um segundo) no final do conjunto de resultados antes de retornar uma resposta ao driver. Isso é usado para evitar que o driver faça uma sondagem agressiva no servidor quando não houver resultados disponíveis. A opçãomaxAwaitTimeMS
pode ser usada em conjunto comtailable
eawaitData
para especificar a quantidade de tempo que o servidor deve bloquear quando atingir o final do o conjunto de resultados.
Ao iterar sobre o objeto cursor, os dados BSON são convertidos em variáveis PHP. Esta iteração pode causar as seguintes exceções: