Diferença entre getSize () e count () na coleção

82

Já ouvi muitas vezes que ambos são iguais. Mas estou enfrentando um problema estranho: na coleção de produtos do módulo CatalogSearch, count () está retornando a contagem correta de produtos, enquanto getSize () está retornando zero.

Então, basicamente é isso que estou recebendo:

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

Mas quero que o getSize () tenha a contagem correta, pois decide se exibirá paginação e produtos na página de pesquisa ou não. Estou usando as condições Inner Join, Left Join e Where apenas na coleção para ser mais específico.

Alguma idéia de por que estou recebendo esse problema estranho?

obrigado

ATUALIZAR:

Minha pergunta anterior, Como clonar a coleção no Magento? Eu queria realizar duas operações diferentes em uma coleção. A primeira coleção mostra getSize () correto, mas, se o getSize () for zero, removi a cláusula WHERE e forneci a nova condição WHERE. Depois disso, estou obtendo o SQL bruto correto, o que eu esperava, e executá-lo no MySQL também fornece um conjunto correto de registros, mas apenas getSize () na coleção está dando zero contagens.

Então, basicamente, talvez eu precise recarregar a coleção, pois getSize () está levando a contagem antiga. Faz sentido?

MagExt
fonte

Respostas:

84

A maioria (se não todas) das coleções se estende Varien_Data_Collection_Db. Aqui estão os 2 métodos desta classe

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);
}

Há uma diferença. Para getSize()a coleção não está carregada. Pois count()é. Geralmente, os modelos de coleção usam o mesmo getSize()método acima e substituem apenas getSelectCountSql().
No getSelectCountSql()limite é redefinido para obter o número total de registros disponíveis para os filtros definidos ( whereinstrução). Veja como getSelectCountSql()funciona

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;
} 
Marius
fonte
3
Ótimo! Então, qual deve ser o meu próximo passo para recarregar a coleção para que ela possa ficar correta getSize()? Obrigado!
MagExt 23/05
Sinceramente, não sei por que você obtém esse resultado. No CatalogSearchmódulo, não há nada que substitua getSize()ou getSelectCountSql(). Ele deve funcionar por padrão, a menos que você tenha adicionado algum código personalizado. Você pode postar a maneira como cria a coleção?
Marius
atualizou a pergunta.
MagExt
3
Não há como redefinir _totalRecords. Você pode tentar clonar a coleção antes de chamar getSize()a coleção original. Talvez isso funcione.
Marius
você também pode fazer algo assim para obter uma contagem de "redefinição":$sql = $collection->getSelectCountSql(); return $collection->getConnection()->fetchOne($sql);
koosa 18/11/16
14

Seja cuidadoso. Isso está correto, mas os métodos são substituídos Varien_Data_Collection_Dbconforme descrito por Marius

Basta dar uma olhada

// \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);
}

Portanto, nesse nível baixo, deve ser o mesmo. Ambos os métodos carregam a coleção e contam os itens.

ATUALIZAR

Oh, eu vejo um problema: getSize () armazena em cache os _totalRecords, isso significa que não é recalculado. Verifique onde _totalRecordsestá definido?

Fabian Blechschmidt
fonte
Sim, eu olhei para ele, mas não consigo entender por que os dois estão gerando contagens diferentes para a mesma coleção? Alguma idéia de como recarregar a coleção ou algo para obter a contagem correta getSize()?
MagExt 23/05
atualizados a entrada
Fabian Blechschmidt
1
getSize()não carrega a coleção para registros provenientes da base de dados. A menos que você substitua o método e diga para carregar a coleção.
Marius
_totalRecords está protegido, portanto não pode chamá-lo no meu arquivo personalizado com coleção. echo count($collection->load()->getItems());dá contagem correta, mas novamente eu quero getSize()trabalhar.
MagExt 23/05
5

Esta resposta aparece no google para "magento getSize errado" e pesquisas semelhantes, então eu gostaria de adicionar um cenário possível que possa ser útil para alguém

Quando você tem uma instrução de grupo em sua consulta e faz uma

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

O Mysql retornará uma contagem para EACH dos grupos, então Varien_Data_Collection_Db :: getSize () retornará a resposta errada, isso ocorre porque esta função busca a primeira linha:

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

Quando preenche

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

Ele seleciona a primeira linha e, portanto, retorna o total do primeiro grupo como o tamanho total.

Acabei criando esse código para contar, com base nos valores exclusivos dos atributos na minha consulta.

$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);
changeling
fonte
2

Caso você acabe aqui, existe outra solução simples para tentar:

System -> Index Management

e selecione todos eles (mesmo que estejam indicando "Verde, não é necessário reindexar" e forçá-los a reindexar.

Isso resolveu meu getSize()problema vazio , que, por sua vez, permitiu que as solicitações de banco de dados Especial e Novo encontrassem os produtos, cumprissem as condições "se" e renderizassem corretamente.

BVRoc
fonte
0

Quando count($collection)era diferente do que $collection->getSize()eu tinha para reindexos produtos, então tudo funcionou bem.

Zsolti
fonte
-1

Há uma diferença principal Para getSize (), a coleção de produtos não é carregada. Para count (), ele carregará toda a coleção de produtos. Portanto, para grandes catálogos, não é aconselhável usar a função de contagem em nenhuma coleção.

Nayan Baraiya
fonte
Já disse no post Marius ...
sv3n