基本Doctrine MongoDB抛出的内存不足异常

时间:2013-10-02 07:15:32

标签: mongodb doctrine

我的数据库中有大约60k文档,我无法查询它们。我能够成功检索它们的唯一方法是使用hydrate(false)选项。

我试过了两个:

$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(),则为false。我相信那是因为我还没有利用它。我尝试做的任何访问都会导致内存问题。甚至像$ 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时,dev调试栏会说该查询使用了120MB的内存。我需要能够遍历所有结果,并且它不能被分页。在没有100MB +查询的情况下,这似乎应该是可能的......

2 个答案:

答案 0 :(得分:0)

我只需要来自两个字段的不同数据,所以这就是我最终要做的事情:

$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);

答案 1 :(得分:0)

由于Doctrine MongoDB ODM是一个持久性管理器(对于关系数据库也是Doctrine ORM 2.x),对水合对象的引用存储在内部,并且不会被PHP的垃圾收集恢复,就像你在迭代非水合阵列的结果很快就会留下范围。

对于Doctrine中的任何批处理操作,您需要定期clear()所有托管对象的对象管理器,或手动detach()单个对象。在您的情况下,定期clear()可能是最简单的,因为您可以在结果中每X次迭代执行一次。您可以在this blog post中找到一些代码示例和对此解决方案的讨论。虽然它是从ORM及其EntityManager类的角度编写的,但ODM的DocumentManager从Doctrine Common库实现了相同的ObjectManager接口,您可以在其中找到detach()clear()方法。

相关问题