Difference between getSize() and count() on collection

I have heard many times that they both are the same. But I am facing a weird issue, in the product collection of CatalogSearch module, count() is returning correct product count while getSize() is returning zero.

So, basically this is what I am getting:

$collection->count(); //correct count
$collection->getSize(); //0

But I want the getSize() to have correct count as it decides whether to show pagination and products in the search page or not. I am using Inner Join, Left Join and Where condition only in the collection to be more specific.

Any ideas why I am getting this weird issue?

Thanks

UPDATE:

My previous question, How to clone the collection in Magento? I wanted to perform two different operations on one collection. The first collection shows correct getSize(), but then if the getSize() is zero, I removed the WHERE clause and gave new WHERE condition. After this, I am getting correct raw SQL what I expected, and running it in MySQL also gives a correct set of records, but only getSize() on the collection is giving zero counts.

So basically I may need to reload the collection, as getSize() is taking old count. Makes sense?

Solutions

Be careful. This is correct, but the methods are overwritten in Varien_Data_Collection_Db as described by Marius

Just have a look into

// \Varien_Data_Collection::getSize
public function getSize()
{
    $this->load();
    if (is_null($this->_totalRecords)) {
        $this->_totalRecords = count($this->getItems());
    }
    return intval($this->_totalRecords);
}

// \Varien_Data_Collection::count
public function count()
{
    $this->load();
    return count($this->_items);
}

So it should on this low level be the same. Both methods load the collection and count the items.

UPDATE

Oh I see a problem: getSize() caches the _totalRecords, this means it is not recalculated. Check where _totalRecords is set?

Most (if not all) the collections extend Varien_Data_Collection_Db. Here are the 2 methods from this class

public function getSize()
{
    if (is_null($this->_totalRecords)) {
        $sql = $this->getSelectCountSql();
        $this->_totalRecords = $this->getConnection()->fetchOne($sql, $this->_bindParams);
    }
    return intval($this->_totalRecords);
} 

public function count() //inherited from Varien_Data_Collection
{
    $this->load();
    return count($this->_items);
}

There is a difference. For getSize() the collection is not loaded. For count() it is. Usually collection models use the same getSize() method as above and only override getSelectCountSql().
In getSelectCountSql() the limit is reset in order to get the total number of records available for the set filters (where statement). See how the getSelectCountSql() works

public function getSelectCountSql()
{
    $this->_renderFilters();
    $countSelect = clone $this->getSelect();
    $countSelect->reset(Zend_Db_Select::ORDER);
    $countSelect->reset(Zend_Db_Select::LIMIT_COUNT);
    $countSelect->reset(Zend_Db_Select::LIMIT_OFFSET);
    $countSelect->reset(Zend_Db_Select::COLUMNS);
    $countSelect->columns('COUNT(*)');
    return $countSelect;
} 

This answer shows up in google for "magento getSize wrong" and similar searches so I would like to add a possible scenario that might be useful to someone

When you have a group statement in your query and you do a

SELECT COUNT(DISTINCT e.entity_id) ... GROUP BY ( at_id_art.value )

Mysql will return a count for EACH of the groups, so Varien_Data_Collection_Db::getSize() will return the wrong answer, this is because this function fetches the first row:

public function getSize()
{
    if (is_null($this->_totalRecords)) {
        $sql = $this->getSelectCountSql();
        $this->_totalRecords = $this->getConnection()->fetchOne($sql, $this->_bindParams);
    }
    return intval($this->_totalRecords);
}

When it populates

$this->_totalRecords = $this->getConnection()->fetchOne($sql, $this->_bindParams);

It selects the first row and therefore returns the total of the first group as the total size.

I ended up coming up with this code to count, based on the unique values of the attributes in my query.

$select = clone $collection->getSelect();
$group = $select->getPart(Zend_Db_Select::GROUP);
$select->reset(Zend_Db_Select::GROUP)->reset(Zend_Db_Select::COLUMNS)->columns("COUNT(DISTINCT {$group[0]})");
$totalCount = $collection->getConnection()->fetchOne($select);

Similar questions

Why getSize() function is not working when apply filter
I want to get count after the collection filter by attributes.Actually i want filter order collections by non canceled ,non fraud' and use getSize() function to get count but it is given count result as when any filters not applied. Please suggest what i do in this caseto get proper result of count.I have order 630 and when i use count() function o...
Customer join query result getSize() issue
join query with customer table getSize() count mismatch with the mysql db result. see the screen below:
Fatal error: Call to a member function getSize() on a non-object
i am using following code in view.phtml : but i am getting error : Fatal error: Call to a member function getSize() on a non-object in line : if ($sellerProductInfo->getSize() == 0)
Which class has getSize() in magento2
How to get the total no of products in our custom filters as below. Desktops(54) i believe its getSize(), but not sure where it is used in Magento2? Is it from Magento\Catalog\Model\ResourceModel\Product\Collection??
Magento getCollection()->getSize() giving wrong value
custom filter of getLoadedProductCollection() function, getSize() method does not give correct value
Magento2: unable to get Actual result by using getSize()?
Collection I am trying to get $this->_productCollection->getSize() which doesnot reflect proper result.

Also ask

We use cookies to deliver the best possible experience on our website. By continuing to use this site, accepting or closing this box, you consent to our use of cookies. To learn more, visit our privacy policy.