0

我的数据库中有大约 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() 它是错误的。我相信那是因为那时我还没有使用它。我尝试做的任何访问都会导致内存问题。甚至像 $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+ 的查询应该是可能的......

4

2 回答 2

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);
于 2013-10-03T16:24:48.927 回答
0

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

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

于 2013-10-21T20:55:38.423 回答