Magento

Mass delete products in Magento

By 1st May 2010September 16th, 201517 Comments

Please note. This article applies to Magento 1.4 and greater only. Some elements of the code are compatible with 1.3, but it will not work in 1.3 and below without modification.

If you have a BIG catalogue - you soon find out that management via the admin can just become tedious. We performed a product import of 80,000 products which unfortunately was supplied with inaccurate information.

Because of the complexity of the products and sheer volume of attributes- it is quicker to delete then reimport. But deleting via the admin for 80k products is nigh on impossible.

The easiest way to pull this off is by means of a quick script. The key to this script is that the indexing functionality is disabled entirely for the process, then enabled again at the end - requiring a manual update at the end, or you could code in an index refresh using our article on refreshing catalogue indexes using a php script.

<?php
ob_end_flush();
echo "Started " . date("d/m/y h:i:s") . "rn";
define('MAGENTO', "/domains/example.com/http");
require_once MAGENTO . '/app/Mage.php';
umask(0);
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
$products = Mage::getModel('catalog/product')->getCollection()->addFieldToFilter('data_set', 1544);
$sql = "";
$undoSql = "";

for ($i = 0; $i <= 8; $i++) {
    $sql.= "UPDATE index_process SET mode = 'manual' WHERE index_process.process_id =$i LIMIT 1;";
    $undoSql.= "UPDATE index_process SET mode = 'real_time' WHERE index_process.process_id =$i LIMIT 1;";
}

$mysqli = Mage::getSingleton('core/resource')->getConnection('core_write');
$mysqli->query($sql);
$total_products = count($products);
$count = 0;

foreach($products as $product) {
    $product->delete();
    if ($count++ % 100 == 0) {
        $cur = strtotime(date("d/m/y h:i:s")) - $time;
        $time = strtotime(date("d/m/y h:i:s"));
        echo round((($count / $total_products) * 100) , 2) . "% deleted ($count/$total_products) " . round(100 / $cur) . " p/s " . date("h:i:s") . "rn";
        flush();
    }
}

echo "Ended " . date("d/m/y h:i:s") . "rn";
$mysqli->query($undoSql);
exit();

In our case, we filtered the type of products by its "Data Set" - an attribute assigned to that batch of products, but you can change this to suit any means of filtering.

The above script runs at around 25 products deleted per second.