Efficiently update prices for multiple products in Magento 2

I have been writing a module to update the prices of an arbitrary set of products based on specific criteria. My problem is that, the update of the prices seems to be very slow. I have been using ProductRepository to handle this, below is a sample code:

$result = $this->productRepository->getList($this->
$products = $result->getItems();
foreach ($products as $product) {
    $product->setPrice(67.74);
    $this->productRepositoryInterface->save($product);
}

Saving the price for 2000+ products takes about 3 minutes. I suspect that every save call makes a separate operation on the db.

For comparison, merely fetching the products and printing them in a file takes mere seconds.

I'd like to know if there is a way to bulk save the products after all the prices have been set.

Also, normally the above operations (again, I guess each and every save) trigger the indexer, thus the operation takes forever to finish unless I have the indexer set to schedule instead of realtime. If possible, I would also like a solution about bypassing the indexer for the duration of the script only.

Answers 1

  • \Magento\Catalog\Api\BasePriceStorageInterface is designed for quick price updates. You need to specify only sku, store id, and price of product and this API allow to do it in batch.

    What the BasePriceStorageInterface update function gets as parameter is an array whose elements are of type \Magento\Catalog\Api\Data\BasePriceInterface, and you need a \Magento\Catalog\Api\Data\BasePriceInterfaceFactory injected in your class to call its create function for each product you wish to update. BasePriceInterface has setPrice, setStoreId, setSku and setExtensionAttributes to set the respective values before putting the element in the array. The respective get... functions exist too. The update function updates the data given in the array atomically in the database and does not trigger the indexer until it is finished.

    For reference, updating the prices of all the 2046 products of the sample Magento catalog this way takes 12 seconds.


Related Questions