Les » curseurs à queue
sont un type spécial de curseur MongoDB qui permet au client de lire
quelques résultats et d'attendre jusqu'à ce que plus de documents
deviennent disponibles. Ces curseurs sont principalement utilisés avec
» Capped Collections
et » Change Streams.
Bien que les curseurs normaux puissent être parcourus une fois avec
foreach, cette approche ne fonctionnera pas avec les
curseurs à queue. Lorsque foreach est utilisé avec un
curseur à queue, la boucle s'arrêtera à la fin du jeu de résultats initial.
Tenter de continuer l'itération sur le curseur avec une seconde
foreach lèverait une exception, car PHP tente de
rembobiner le curseur. Comme pour les objets result dans d'autres pilotes
de base de données, les curseurs dans MongoDB prennent uniquement en charge
l'itération en avant, ce qui signifie qu'ils ne peuvent pas être rembobinés.
Afin de lire en continu à partir d'un curseur de queue, l'objet Cursor doit
être enveloppé avec un IteratorIterator. Cela permet
à l'application de contrôler directement l'itération du curseur, d'éviter
de rembobiner par inadvertance le curseur et de décider quand attendre les
nouveaux résultats ou arrêter complètement l'itération.
Afin de démontrer un curseur en action, deux scripts seront utilisés: un
"Producer" et un "Consumer". Le script Producer créera une nouvelle collection
plafonnée à l'aide de la commande
» Create et
procédera à l'insertion d'un nouveau document dans cette collection
chaque seconde.
<?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);
}
?>
Avec le script Producer toujours en cours d'exécution, un deuxième script
consommateur peut être exécuté pour lire les documents insérés à l'aide
d'un curseur de queue, indiqué par les options tailable
et 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("Consumed document created at: %s\n", $document->createdAt);
}
$iterator->next();
}
?>
Le script consommateur va commencer par imprimer rapidement tous les
documents disponibles dans la collection plafonnée (comme si
foreach avait été utilisé); toutefois, il ne se
terminera pas à la fin du jeu de résultats initial. Étant donné que
le curseur est en file d'attente, l'appel de
IteratorIterator::next() se bloque et attend des
résultats supplémentaires. IteratorIterator::valid()
est également utilisé pour vérifier s'il y a effectivement des données
disponibles à lire à chaque étape.