2

Code:

try {
  $documentsFind = $client->$db->$collection->find([
      // query
  ]);
  if ($documentsFind) {
    foreach ($documentsFind as $product) {
    // code...
    }
  }
catch (MongoCursorException $e) {
  echo "error message: ".$e->getMessage()."\n";
  echo "error code: ".$e->getCode()."\n";
}

Error:

Fatal error: Uncaught MongoDB\Driver\Exception\RuntimeException: Cursor not found, cursor id: 31837896248 in ...

It seems that the cursor does exist but times out? How can I prevent that from happening?

Edited to add: I tried doing:

 if ($documentsFind) {
    $documentsFind->immortal(true); // keep alive
    foreach ($documentsFind as $product) {
    // code...
    }
  }

But that results in Call to undefined method MongoDB\Driver\Cursor::immortal().

Somnath Muluk
  • 55,015
  • 38
  • 216
  • 226
eozzy
  • 66,048
  • 104
  • 272
  • 428
  • Does the error appears on the first run or are you able to load some entries? – cb0 Jun 21 '16 at 09:12
  • It fetches quite a few documents from the DB but times out at some point. I was able to bypass this temporarily with `mongod --setParameter cursorTimeoutMillis=9000000` – eozzy Jun 21 '16 at 13:06

2 Answers2

7

Try querying like this:

$documentsFind = $client->$db->$collection->find([
  // query
], ['noCursorTimeout' => true]);

find() method passes the 2nd argument to the Find class constructor, so you can see all the available options here

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
0

Cursor exception says,

The driver was trying to fetch more results from the database, but the database did not have a record of the query. This usually means that the cursor timed out on the server side: after a few minutes of inactivity, the database will kill a cursor.

The MongoDB PHP driver has two different timeouts:

  1. Connection timeout
  2. Cursor timeout

Make sure you use timeout or immortal on the cursor:

$cursor = $collection->find();
$cursor->immortal(true); 
$cursor->timeout(-1);

Note: Timeout indicates the time to wait on the client side while immortal sets the cursor on the server side.

But I would suggest if you have cursor of big data size then you should fetch cursor data in chunks like:

Get the first 1000 documents from collection, process them. Then get the next 1000 documents. You can do this by skip and limit.

Somnath Muluk
  • 55,015
  • 38
  • 216
  • 226
  • 2
    Tried all of that. It appears that `immortal` and `timeout` are not available on the new PHP driver `mongodb`, not `mongo`. – eozzy Jun 23 '16 at 00:37
  • Which mongodb version you are using? Are you getting cursor object for find()? Which php mongo driver you have? @3zzy – Somnath Muluk Jun 23 '16 at 06:01