Php 在不耗尽内存的情况下迭代Mongo结果

Php 在不耗尽内存的情况下迭代Mongo结果,php,mongodb,mongodb-query,Php,Mongodb,Mongodb Query,我需要在每个文档的名称/描述/标签等中找到关键字,如果找到,则将其删除。我是Mongo的新手,所以我在现有的代码库中遵循类似的脚本。首先,获取MongoCursor,只获取我们要检查的字段: /** @var MongoCursor $products */ $products = $collection->find( ['type' => ['$in' => ['PHONES', 'TABLETS']], 'supplier.is_awful'

我需要在每个文档的名称/描述/标签等中找到关键字,如果找到,则将其删除。我是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
中看到了一些希望,但看起来我需要在那里有一个索引(我没有),每个集合只能有一个文本索引。

您不需要全文索引来查找子字符串:正确的方法是使用a,然后只返回“\u 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语法,但关键是一个包含$or的过滤器,在两个字段上使用相同的mongodb正则表达式。

…当然,您将循环结果以删除$manager集合中的所有_id;优化可以通过使用“$in”子句提供整个$id列表(或者至少很多,限制通常是16Gb的BSON)来进行大容量删除,这样您就可以避免大量的数据库往返。您有没有找到解决方案?我也看到了同样的问题,我的光标占用了越来越多的内存,没有任何明显的方法来阻止它。@Boerema不幸的是,没有。我只是在脚本中增加了PHP的内存限制。据我所知(已经有一段时间了,雾蒙蒙的),泄漏是真的