У меня проблемы с PHP MongoCursor, так как я обновил драйвер PHP Mongo с 1.5.8 до 1.6.0
Следующий код хорошо работает с версией 1.5.8, но вылетает с версией 1.6
Версия PHP 5.5.21., Версия Apache — Apache / 2.4.10 (Ubuntu).
$mongoClient = new \MongoClient($serverUrl, ['readPreference'=>\MongoClient::RP_NEAREST]);
$database = $mongoClient->selectDB($dbName);
$collection = $database->selectCollection($collectionName);
// count() works fine and returns the right nb on documents
echo '<br/>count returned '.$collection->count();
// find() exectues with no error...
$cursor = $collection->find();
$documents = [];
// ...and hasNext() crashes with the Excetion below
while($cursor->hasNext()){$documents[] = $cursor->getNext();}
return $documents;
И поэтому вызов hasNext () завершается с этим сообщением:
КРИТИЧЕСКИЙ: MongoException: объект MongoCursor не был правильно инициализирован его конструктором (неперехваченное исключение) …
Я делаю что-то неправильно ?
Спасибо за помощь!
Это может быть связано с ошибкой, которая была введена в 1.6.0 относительно итерации с hasNext()
а также getNext()
: PHP-1382. С тех пор исправление было объединено с v1.6
ветка и должен быть выпущен позже на этой неделе как 1.6.1.
Тем не менее, ошибка, касающаяся hasNext()
на самом деле последний документ в наборе результатов будет пропущен во время итерации. Если я запускаю ваш оригинальный скрипт против 1.6.0, массив содержит null
значение как его последний элемент. После исправления массив будет содержать все документы, как и ожидалось. Я не могу воспроизвести исключение, которое вы видите с любой версией.
Это исключение фактически выдается из внутренних проверок структур данных C, чтобы гарантировать, что объект курсора должным образом связан с MongoClient и соединением с сокетом. Увидеть MONGO_CHECK_INITIALIZED()
макро вызовы в этот файл. Большинство всех методов курсора проверяют, связан ли MongoClient, но hasNext()
уникален тем, что он также проверяет объект сокета (я полагаю, что другие методы просто предполагают, что курсор с MongoClient также имеет сокет). Если это исключение действительно воспроизводимо для вас, и вы хотите выполнить некоторую отладку с расширением, мне было бы очень интересно узнать, какая из двух проверок выдает ошибку.
В качестве примечания вы должны также указать "replicaSet"
опция при построении MongoClient. Это должно иметь имя набора реплик, которое гарантирует, что драйвер может должным образом игнорировать соединения с хостами, которые не являются членами предполагаемого набора реплик.
Я только что столкнулся с той же проблемой; Я реорганизовал свой код, чтобы использовать вместо него итератор курсора, то есть:
foreach( $cursor as $doc ) {
$documents[] = $doc;
}
Я искал пример кода, как реализовать настраиваемый курсор, и нашел этот вопрос. Следующий код представляет собой простой пример настраиваемого курсора (через переменную $ cursor), который вы предоставляете в ограниченной коллекции mongodb.
$cursor->tailable(true);
$cursor->awaitData(true);
while (true) {
if ($cursor->hasNext()) {
var_dump($cursor->getNext());
} else {
if ($cursor->dead()) {
break;
}
}
}