迭代Mongo结果而不会耗尽内存

时间:2015-08-30 22:02:44

标签: php mongodb mongodb-query

我需要在每个文档的名称/说明/标签等中找到关键字,如果找到它们就将其删除。我是Mongo的新手,所以我在现有代码库中遵循类似的脚本。首先,获取MongoCursor并获取我们将要检查的字段:

    /** @var MongoCursor $products */
    $products = $collection->find(
        ['type' => ['$in' => ['PHONES', 'TABLETS']], 'supplier.is_awful' => ['$exists' => true]],
        ['details.name' => true, 'details.description' => true]
    );

然后,遍历每个文档,然后检查每个属性以获取我们感兴趣的值:

/** @var \Doctrine\ODM\MongoDB\DocumentManager $manager */
$manager = new Manager();

foreach ($products as $product) {
    // Find objectionable words in the content and remove these documents
    foreach (["suckysucky's", "deuce", "a z z"] as $word) {
        if (false !== strpos(mb_strtolower($product['details']['name']), $word)
          || false !== strpos(mb_strtolower($product['details']['description']), $word)) {
                $object = $manager->find(\App\Product::class, $product['_id']);
                $manager->remove($object);
        }
    }
}
// Persist to DB
$manager->flush();

问题是数据库有成千上万的记录,看起来像是在MongoCursor上进行迭代,内存使用率一直在上升,直到它用完为止:

Now at (0) 20035632
Now at (100) 24446048
Now at (200) 32190312
Now at (300) 36098208
Now at (400) 42433656
Now at (500) 45204376
Now at (600) 50664808
Now at (700) 54916888
Now at (800) 59847312
Now at (900) 65145808
Now at (1000) 70764408

我有没有办法迭代MongoCursor而不会耗尽内存(我已经尝试在不同的位置取消设置各种对象,但没有运气)?或者,这是一个可以直接在Mongo中运行的查询吗?我查看了文档,我在$text看到了一些希望,但看起来我需要在那里有一个索引(我不会),并且只能有一个文本索引每个系列。

1 个答案:

答案 0 :(得分:0)

您不需要全文索引来查找子字符串:正确的方法是使用regex,然后只返回“_id”值,如:

$mongore = new MongoRegex("/suckysucky's|deuce|a z z/i")
$products = $collection->find(
    ['type' => ['$in' => ['PHONES', 'TABLETS']], 
     'supplier.is_awful' => ['$exists' => true],
     '$or': [['details.name' => $mongore],
             ['details.description' => $mongore]]]
    ['_id' => true]
);

我不确定确切的PHP语法,但关键是包含$或过滤器,在两个字段上使用相同的mongodb正则表达式。