我的数据库中有大约 60k 文档,但我无法查询它们。 我能够成功检索它们的唯一方法是使用水合物(假)选项。
我都尝试过:
$dm = $this->get('doctrine_mongodb')->getManager();
$qb = $dm->createQueryBuilder('BConwayWebsiteBundle:Business')
->eagerCursor(true);
$query = $qb->getQuery();
$results = $query->execute();
和
$dm = $this->get('doctrine_mongodb')->getManager();
$qb = $dm->createQueryBuilder('BConwayWebsiteBundle:Business');
$query = $qb->getQuery();
$results = $query->execute();
如果我转储 $results->isInitialized() 它是错误的。 我相信这是因为我当时还没有使用它。 我尝试执行的任何访问都会导致内存问题。 甚至像 $results->count() 这样基本的东西。
[2013-10-01 23:54:55] doctrine.INFO: MongoDB query: {"find":true,"query":[],"fields":[],"db":"ClosedForTheHoliday","collection":"businesses"} [] []
[2013-10-01 23:54:55] doctrine.INFO: MongoDB query: {"limit":true,"limitNum":null,"query":[],"fields":[]} [] []
[2013-10-01 23:54:55] doctrine.INFO: MongoDB query: {"skip":true,"skipNum":null,"query":[],"fields":[]} [] []
[2013-10-01 23:54:55] doctrine.INFO: MongoDB query: {"sort":true,"sortFields":[],"query":[],"fields":[]} [] []
[2013-10-01 23:54:56] emergency.EMERGENCY: Allowed memory size of 134217728 bytes exhausted (tried to allocate 32 bytes) {"type":1,"file":"/media/sf_sites/cfth_com/vendor/doctrine/mongodb/lib/Doctrine/MongoDB/Cursor.php","line":237} []
更新:如果我将结果限制为 2000,它就有效。 此外,如果我只选择查询后要使用的两个字段,我可以将其限制为 15000 并获得成功。 当我将其限制为 2000 时,开发调试栏显示查询使用了 120MB 内存。 我需要能够迭代所有结果,并且它无法分页。 看来没有 100MB 以上的查询就应该可以实现...
我只需要来自两个字段的不同数据,所以这就是我最终所做的:
$dm = $this->get('doctrine_mongodb')->getManager();
// Get organization name from all businesses (distinct)
$organizations = $dm->createQueryBuilder('BConwayWebsiteBundle:Business')
->distinct('organization')
->getQuery()
->toArray();
// Get business name from all businesses (distinct)
$names = $dm->createQueryBuilder('BConwayWebsiteBundle:Business')
->field('organization')->equals('')
->field('organization')->equals(null)
->distinct('name')
->getQuery()
->toArray();
// Create new array from results of both queries
$businesses = array_merge($organizations, $names);
// Filter out any null or empty values
$businesses = array_filter($businesses, function($item) {
return (!is_null($item) && strlen($item) > 0);
});
// Filter out any duplicates
array_unique($businesses);
// Sort array case-insensitive
sort($businesses, SORT_STRING | SORT_FLAG_CASE);
由于 Doctrine MongoDB ODM 是一个持久性管理器(与关系数据库的 Doctrine ORM 2.x 类似),对水合对象的引用存储在内部,并且不会像迭代非水合数组那样容易被 PHP 的垃圾回收恢复结果很快就超出了范围。
对于 Doctrine 中的任何批处理操作,您需要定期
clear()
所有托管对象的对象管理器,或手动 detach()
单个对象。在您的情况下,定期 clear()
可能是最简单的,因为您可以在结果的每 X 次迭代中执行此操作。您可以在这篇博文中找到一些代码示例以及对此解决方案的讨论。尽管它是从 ORM 及其 EntityManager 类的角度编写的,但 ODM 的 DocumentManager 实现了 Doctrine Common 库中相同的 ObjectManager 接口,您可以在其中找到 detach()
和 clear()
方法。