PHP 8.4.0 RC4 available for testing

La classe MongoDB\Driver\Cursor

(mongodb >=1.0.0)

Introduction

La classe MongoDB\Driver\Cursor encapsule le résultat d'une commande ou d'une requête MongoDB, pouvant être retournée par, respectivement, MongoDB\Driver\Manager::executeCommand() ou MongoDB\Driver\Manager::executeQuery().

Synopsis de la classe

final class MongoDB\Driver\Cursor implements MongoDB\Driver\CursorInterface, Iterator {
/* Méthodes */
final private __construct()
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
}

Historique

Version Description
PECL mongodb 1.9.0 Implémente Iterator.
PECL mongodb 1.6.0 Iméplémentation de MongoDB\Driver\CursorInterface, qui étend Traversable.

Exemples

Exemple #1 Lecture d'un jeu de résultats

MongoDB\Driver\Manager::executeCommand() et MongoDB\Driver\Manager::executeQuery() les deux renvoient leur (s) résultat (s) en tant qu'objet MongoDB\Driver\Cursor. Cet objet peut être utilisé pour itérer au sein du jeu de résultats de la commande ou de la requête.

Parce que MongoDB\Driver\Cursor implémente l'interface Traversable, vous pouvez simplement itérer sur le jeu de résultats avec foreach.

<?php

$manager
= new MongoDB\Driver\Manager();

/* Insérez des documents afin que notre requête renvoie des informations */
$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);

/* Requête pour tous les éléments de la collection */
$query = new MongoDB\Driver\Query( [] );

/* Interrogez la collection "asteroids" de la base de données "test" */
$cursor = $manager->executeQuery("test.asteroids", $query);

/* $cursor contient maintenant un objet qui entoure le jeu de résultats.
* Utilisez foreach() pour itérer sur tous les résultats */
foreach($cursor as $document) {
print_r($document);
}

?>

Résultat de l'exemple ci-dessus est similaire à :

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
}

Exemple #2 Lecture d'un jeu de résultats pour un curseur à queue

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.

Note: Cet exemple utilise l'option de requête awaitData pour indiquer au serveur de bloquer pendant une courte période (par exemple une seconde) à la fin du jeu de résultats avant de retourner une réponse au pilote. Ceci est utilisé pour empêcher le pilote d'interroger agressivement le serveur lorsqu'il n'y a aucun résultat disponible. L'option maxAwaitTimeMS peut être utilisée conjointement avec tailable et awaitData pour spécifier la durée pendant laquelle le serveur doit se bloquer lorsqu'il atteint la fin du jeu de résultats.

Erreurs / Exceptions

Lors de l'itération sur l'objet Cursor, les données BSON sont converties en variables PHP. Cette itération peut provoquer les exceptions suivantes:

Sommaire

add a note

User Contributed Notes 5 notes

up
16
max-p at max-p dot me
8 years ago
As one might notice, this class does not implement a hasNext() or next() method as opposed to the now deprecated Mongo driver.

If, for any reason, you need to pull data from the cursor procedurally or otherwise need to override the behavior of foreach while iterating on the cursor, the SPL \IteratorIterator class can be used. When doing so, it is important to rewind the iterator before using it, otherwise you won't get any data back.

<?php
$cursor
= $collection->find();
$it = new \IteratorIterator($cursor);
$it->rewind(); // Very important

while($doc = $it->current()) {
var_dump($doc);
$it->next();
}
?>

I used this trick to build a backward compatibility wrapper emulating the old Mongo driver in order to upgrade an older codebase.
up
5
tdrpic
8 years ago
If you find that it would be easier to use arrays (instead of objects) for the returned documents, add the following after executing your query:

$cursor->setTypeMap(['root' => 'array', 'document' => 'array', 'array' => 'array']);
up
4
mikemartin2016 at gmail dot com
8 years ago
I noticed that ->sort is missing from the cursor. Seems like the old driver has more functionality.

[red.: The way how cursors are created is different between the drivers. In the old driver, the cursor would not be created until after the first rewind() call on the iterator.

In the new driver the cursor already exists. Because sort (and limit and skip) parameters need to be send to the server, they can not be called after the cursor already has been created.

You can use sort (and limit and skip) with the new driver as well, by specifying them as options to the Query as shown in this example: http://php.net/manual/en/mongodb-driver-query.construct.php#refsect1-mongodb-driver-query.construct-examples]
up
4
peichi40233 at gmail dot com
7 years ago
There used to be a count() method in the old mongo extension (http://docs.php.net/manual/en/mongocursor.count.php), however, this feature seems to be deleted in mongodb.

I've seen some people use executeCommand() to do that, but I found it much more earier to just use the toArray() method and count the returned array.

For example:
$manager = new MongoDB\Driver\Manager();
$query = new MongoDB\Driver\Query($filter, $options);
$cursor = $manager->executeQuery('db.collection', $query)->toArray();
var_dump(count($cursor));
up
1
cg at papoo dot de
3 years ago
Since php-mongodb version 1.9.0 Cursor implements Iterator, but if you need to support older versions too, you can conditionally wrap the cursor with IteratorIterator:

<?php
$iterator
= $collection->find();

if (!(
$iterator implements Iterator)) {
$iterator = new \IteratorIterator($iterator);
}
?>
To Top