【问题标题】:Mongo-PHP - MongoCursor exception with MongoDB PHP Driver v1.6Mongo-PHP - MongoDB PHP 驱动程序 v1.6 的 MongoCursor 异常
【发布时间】:2015-08-17 21:07:02
【问题描述】:

自从我将 Mongo PHP Driver 从 1.5.8 升级到 1.6.0 后,我在使用 PHP MongoCursor 时遇到了问题

以下代码在 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() 调用会因这条消息而崩溃:

CRITICAL: MongoException: MongoCursor 对象没有被其构造函数正确初始化(未捕获的异常)...

我做错了吗? 谢谢你的帮助!

【问题讨论】:

  • 我也有同样的问题
  • @LeonardoDelfino:请参阅下面的回复。我很想知道这对您来说是否也很容易重现,以及您是否愿意进一步调试它。

标签: php mongodb cursor


【解决方案1】:

这可能与 1.6.0 中引入的与 hasNext()getNext():PHP-1382 的迭代有关的错误有关。此后,一个修复程序已合并到 v1.6 branch,并应在本周晚些时候作为 1.6.1 发布。

也就是说,关于hasNext() 的错误实际上是结果集中的最后一个文档在迭代时会丢失。如果我针对 1.6.0 运行您的原始脚本,则该数组包含一个 null 值作为其最后一个元素。修复到位后,数组将按预期包含所有文档。我无法重现您在任一版本中看到的异常。

该异常实际上是从对 C 数据结构的内部检查中引发的,以确保游标对象与 MongoClient 和套接字连接正确关联。请参阅 this file 中的 MONGO_CHECK_INITIALIZED() 宏调用。大多数游标方法都会检查 MongoClient 是否关联,但 hasNext() 的独特之处在于它还检查套接字对象(我相信其他方法只是假设带有 MongoClient 的游标也有套接字)。如果该异常对您来说确实是可重现的,并且您愿意对扩展进行一些调试,那么我很想知道这两项检查中的哪一项引发了错误。


附带说明,您还应该在构建 MongoClient 时指定 "replicaSet" 选项。这应该具有副本集名称,以确保驱动程序可以正确忽略与不属于预期副本集成员的主机的连接。

【讨论】:

【解决方案2】:

我刚刚遇到了同样的问题;我重构了我的代码以使用游标迭代器,即:

foreach( $cursor as $doc ) {
 $documents[] = $doc;
}

【讨论】:

    【解决方案3】:

    我正在寻找如何实现可尾游标的代码示例并发现了这个问题。下面的代码是一个可尾游标的简单示例(通过 $cursor 变量),您可以在一个有上限的 mongodb 集合上提供它。

        $cursor->tailable(true);
        $cursor->awaitData(true);
        while (true) { 
            if ($cursor->hasNext()) { 
                var_dump($cursor->getNext()); 
            } else { 
                if ($cursor->dead()) { 
                   break; 
                }
             } 
        }
    

    【讨论】:

    • 请补充一些细节。纯代码答案没那么有用。
    • 编辑了我的评论以澄清。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2015-10-23
    • 1970-01-01
    • 2016-07-10
    • 2014-02-28
    • 2016-01-09
    • 2012-07-10
    • 1970-01-01
    相关资源
    最近更新 更多