从游标访问数据
概述
在本指南中,您可以了解如何使用 MongoDB PHP 库通过游标访问数据。
游标是一种机制,可以分批返回读取操作的结果。游标通过在任何给定时间只保留文档的子集,而不是一次性返回所有文档,从而减少了内存消耗和服务器请求数量。
当 MongoDB PHP 库通过以下方式执行读取操作时:MongoDB\Collection::find()
方法,它返回匹配的文档在 MongoDB\Driver\Cursor
实例中。
示例数据
本指南中的示例使用来自 Atlas 示例数据集 的 sample_restaurants
数据库中的 restaurants
集合。要访问此集合,从您的 PHP 应用程序中实例化一个连接到 Atlas 集群的 MongoDB\Client
并将以下值分配给您的 $collection
变量
$collection = $client->sample_restaurants->restaurants;
要了解如何创建免费的 MongoDB Atlas 集群并加载示例数据集,请参阅 Atlas 入门 指南。
迭代访问游标内容
MongoDB\Driver\Cursor
类实现了 Iterator
接口,因此您可以使用 foreach
循环遍历其内容。
以下示例使用 MongoDB\Collection::find()
方法检索所有 name
字段值为 'Dunkin' Donuts'
的文档。然后,它通过调用 find()
方法返回的光标打印每个文档
$cursor = $collection->find(['name' => 'Dunkin\' Donuts']); foreach ($cursor as $doc) { echo json_encode($doc), PHP_EOL; }
{"_id":{"$oid":"..."},..."name":"Dunkin' Donuts","restaurant_id":"40379573"} {"_id":{"$oid":"..."},..."name":"Dunkin' Donuts","restaurant_id":"40363098"} {"_id":{"$oid":"..."},..."name":"Dunkin' Donuts","restaurant_id":"40395071"} ...
逐个检索文档
要从光标中检索单个文档,请在 MongoDB\Driver\Cursor
实例上调用 current()
方法。此方法返回光标最初指向的文档。您可以继续通过调用 next()
方法来前进光标,该方法指示光标指向下一个检索到的文档。
以下示例查找所有 name
字段值为 'Dunkin' Donuts'
的文档。然后,通过在光标上调用 current()
方法来打印第一个检索到的文档
$cursor = $collection->find(['name' => 'Dunkin\' Donuts']); $cursor->rewind(); echo json_encode($cursor->current());
{"_id":{"$oid":"..."},..."name":"Dunkin' Donuts","restaurant_id":"40379573"}
检索所有文档
警告
如果查询返回的文档数量和大小超过了可用应用程序内存,则您的程序将崩溃。如果您预期将得到大量结果集,请 迭代地访问您的光标。
要从光标中检索所有文档,可以使用以下任一方法将光标转换为数组
MongoDB\\Driver\\Cursor::toArray()
:在MongoDB\Driver\Cursor
对象上调用iterator_to_array()
:将MongoDB\Driver\Cursor
对象作为参数传递
以下示例在光标上调用 toArray()
方法以将结果存储在数组中
$cursor = $collection->find(['name' => 'Dunkin\' Donuts']); $array_results = $cursor->toArray();
可续游标
当在有界集合上查询时,您可以使用在客户端耗尽游标结果后仍然保持打开的可续游标。要创建一个可续游标,在数组中将cursorType
选项设置为MongoDB\Operation\Find::TAILABLE
。然后,将数组作为选项参数传递给MongoDB\Collection::find()
方法。
例如,您可以使用以下代码创建一个名为vegetables
的有界集合,该集合存储表示蔬菜的文档
$db = $client->db; $create_coll = $db->createCollection( 'vegetables', ['capped' => true, 'size' => 1024 * 1024] ); $vegetables = [ ['name' => 'cauliflower'], ['name' => 'zucchini'] ]; $collection = $db->vegetables; $result = $collection->insertMany($vegetables);
以下代码使用可续游标检索vegetables
集合中的所有文档。在游标耗尽后,它将保持打开状态,直到检索到三个文档
$cursor = $collection->find([], ['cursorType' => MongoDB\Operation\Find::TAILABLE]); $cursor->rewind(); $docs_found = 0; while ($docs_found < 3) { if ($cursor->valid()) { $doc = $cursor->current(); echo json_encode($doc), PHP_EOL; $docs_found++; } $cursor->next(); }
{"_id":{"$oid":"..."},"name":"cauliflower"} {"_id":{"$oid":"..."},"name":"zucchini"}
如果您将另一个文档插入到vegetables
集合中,前面的代码将打印新文档并关闭while
循环。
有关可续游标的更多信息,请参阅MongoDB服务器手册中的可续游标。
更多信息
有关读取操作的更多信息,请参阅检索数据指南。
有关游标的更多信息,请参阅以下扩展API文档中的页面
API 文档
了解更多关于 find()
方法的信息,请参阅 MongoDB\Collection::find()
的 API 文档。