0

I have added a collection to buff out related products with extra "most viewed" products from a products top level category.

This is a slow query and takes about 0.2 seconds so was wondering if this collection can be cached with a key based on top level category so I can query if this collection exists and add products to the current related products collection from the cached collection instead of rerunning it each time?

Something like below but this was for Magento 1:

https://stackoverflow.com/questions/3755104/how-to-cache-a-collection-in-magento

There could be anything up to 4000 products that could benefit from pulling products from this cached collection in some cases.

    if($this->_cacheType->load($categoryMain)) {
        $collection = unserialize($this->_cacheType->load($categoryMain));
    } else {
        $collection = $this->mostViewedCollection->addAttributeToSelect(
            ['name','sku','price']
        )->addViewsCount()->setStoreId(
            $storeId
        )->addStoreFilter(
            $storeId
        )->setPageSize(
            $count
        )
        ->addCategoriesFilter(array('in' => $categoryIds));
        $this->_cacheType->save(serialize($collection), $categoryMain, [\Harrigo\AutoAssociatedProducts\Model\Cache\Type::CACHE_TAG], 86400);
    }

The collections however throw an error when being sereialized which leaves me stuck. I do not want to turn it into an array as guess i'll have to rebuild items.phtml to render the collection. I have actually noticed that the main slow down seems to be elsewhere after timing the collections but I am still interested in this and what the proper way to achieve something like above would be.

1

Cache an array of entity ids and reload the collection from that. Also, if the page size is variable, add that to the identifier. See below.

$cache_id = $categoryMain . '_' . $storeId . '_' . $count;
if($this->_cacheType->load($cache_id)) {
    $entity_ids = unserialize($this->_cacheType->load($cache_id));
    $collection = $this->mostViewedCollection
      ->addAttributeToSelect(['name','sku','price'])
      ->addFieldToFilter('entity_id', ['in' => $entity_ids])
      ->addViewsCount();
} else {
    $collection = $this->mostViewedCollection->addAttributeToSelect(
        ['name','sku','price']
    )->addViewsCount()->setStoreId(
        $storeId
    )->addStoreFilter(
        $storeId
    )->setPageSize(
        $count
    );

    $entity_ids = [];
    foreach ($collection as $c) {
        $entity_ids[] = $c->getId();
    }

    $this->_cacheType->save(serialize($entity_ids), $cache_id, [\Harrigo\AutoAssociatedProducts\Model\Cache\Type::CACHE_TAG], 86400);
}

Though I'm having some thoughts that the speed issue might be related to addViewsCount. Might be a good idea to add a cache to that method. Alternatively, a second cache_id with an array of view counts matched to entity_ids and looped into that collection could do the trick if you don't want to plugin to Harrigo\AutoAssociatedProducts.

  • Thanks will accept although have solved this previously thanks for your efforts! – harri May 22 at 15:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.