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 {
/* Méthodes */
final private function __construct()
public function current(): array|object|null
final public function getId(): MongoDB\BSON\Int64
final public function getServer(): MongoDB\Driver\Server
final public function isDead(): bool
public function key(): int
public function next(): void
public function rewind(): void
final public function setTypeMap(array $typemap): void
final public function toArray(): array
public function valid(): bool
}

Historique

Version Description
PECL mongodb 1.9.0 Implémente Iterator.
PECL mongodb 1.6.0 Implé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, il est possible de 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.
* Utiliser 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 ¶
10 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 ¶
9 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 ¶
10 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 ¶
9 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 ¶
4 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);
}
?>