Add products to category quickly!
Posted on | June 4, 2016 | No Comments
When dealing with Magento, the common knowledge to bulk update products is to pull in a collection and, in a loop, load the product, change the attribute and save.
A client is syncing their product database from their system to Magento, but their system only allows a product to be in one category. I was asked to run a cron script nightly to check for an attribute on the product and place those products into an additional category.
Knowing how slow save() is, I started to dig around and come up with the below code.
Benchmarking this code against the regular way of doing it, I saw the times drop from about an hour and a half for 1,200 products to five seconds!
This is the minimum amount of code required to alter a collection of products to add them to a new category. I’ve removed the extra code regarding my scenario above.
Mage::log('Start'); // Set indexing to manual before starting updates, otherwise it'll continually get slower as you update $processes = Mage::getSingleton('index/indexer')->getProcessesCollection(); $processes->walk('setMode', array(Mage_Index_Model_Process::MODE_MANUAL)); $processes->walk('save'); /** @var Varien_Db_Adapter_Pdo_Mysql **/ $dbw = Mage::getSingleton('core/resource')->getConnection('core_write'); $productCategoryTable = Mage::getSingleton('core/resource')->getTableName('catalog/category_product'); $product_ids = Mage::getModel('catalog/product')->getCollection() ->getAllIds(); $category_id = 123; // Add product ids and category ids to database for insertion $data = array(); foreach($product_ids as $id) { $data[] = array( 'category_id' => (int)$category_id, 'product_id' => (int)$id, 'position' => 1, ); } if(count($data)) { // Updates a single attribute, much faster than calling a full product save try { $dbw->insertMultiple($productCategoryTable, $data); } catch (Exception $e) { //ignore duplicate entry error messages if(strpos(strtolower($e->getMessage()), 'duplicate entry') === FALSE) { Mage::log($e->getMessage()); } } } Mage::log('Products Put in Category:'); Mage::log($product_ids); // Reindex all $processes->walk('reindexAll'); // Set indexing back to realtime, if you have it set to manual normally you can comment this line out $processes->walk('setMode', array(Mage_Index_Model_Process::MODE_REAL_TIME)); $processes->walk('save'); Mage::log('End');
Posted By:Richard Parnaby-King