Differenza tra getSize () e count () sulla raccolta


82

Ho sentito molte volte che entrambi sono uguali. Ma sto affrontando uno strano problema, nella raccolta di prodotti del modulo CatalogSearch, count () restituisce il conteggio corretto del prodotto mentre getSize () restituisce zero.

Quindi, sostanzialmente questo è quello che sto ottenendo:

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

Ma voglio che getSize () abbia il conteggio corretto in quanto decide se mostrare l'impaginazione e i prodotti nella pagina di ricerca o meno. Sto usando la condizione Inner Join, Left Join e Where solo nella raccolta per essere più specifici.

Qualche idea sul perché sto ricevendo questo strano problema?

Grazie

AGGIORNARE:

La mia domanda precedente, Come clonare la collezione in Magento? Volevo eseguire due diverse operazioni su una raccolta. La prima raccolta mostra getSize () corretto, ma se getSize () è zero, ho rimosso la clausola WHERE e ho dato la nuova condizione WHERE. Dopo questo, sto ottenendo SQL raw corretto come mi aspettavo, ed eseguirlo in MySQL fornisce anche un set corretto di record, ma solo getSize () sulla raccolta sta dando zero conteggi.

Quindi, in pratica, potrei aver bisogno di ricaricare la raccolta, poiché getSize () sta prendendo il vecchio conteggio. Ha senso?

Risposte:


84

La maggior parte (se non tutte) delle collezioni si estende Varien_Data_Collection_Db. Ecco i 2 metodi di questa 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);
}

C'è una differenza. Per getSize()la raccolta non viene caricato. Perché count()lo è. Di solito i modelli di raccolta utilizzano lo stesso getSize()metodo di cui sopra e sostituiscono solo getSelectCountSql().
Nel getSelectCountSql()limite viene resettato per ottenere il numero totale di record disponibili per i filtri impostati ( whereistruzione). Guarda come getSelectCountSql()funziona

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

3
Grande! Quindi quale dovrebbe essere il mio prossimo passo per ricaricare la raccolta in modo che possa essere corretta getSize()? Grazie!
MagExt

Onestamente non so perché ottieni questo risultato. Nel CatalogSearchmodulo non c'è nulla che abbia la precedenza getSize()o getSelectCountSql(). Dovrebbe funzionare per impostazione predefinita, a meno che non sia stato aggiunto del codice personalizzato. Puoi pubblicare il modo in cui costruisci la collezione?
Marius

aggiornata la domanda.
MagExt

3
Non è possibile ripristinare _totalRecords. Puoi provare a clonare la raccolta prima di chiamare getSize()la raccolta originale. Forse funzionerà.
Marius

puoi anche fare qualcosa del genere per ottenere un conteggio di "reset":$sql = $collection->getSelectCountSql(); return $collection->getConnection()->fetchOne($sql);
koosa

14

Stai attento. Questo è corretto, ma i metodi vengono sovrascritti Varien_Data_Collection_Dbcome descritto da Marius

Dai un'occhiata

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

Quindi a questo livello basso dovrebbe essere lo stesso. Entrambi i metodi caricano la raccolta e contano gli articoli.

AGGIORNARE

Oh, vedo un problema: getSize () memorizza nella cache _totalRecords, questo significa che non viene ricalcolato. Verifica dove _totalRecordsè impostato?


Sì, l'ho visto, ma non riesco a capire perché entrambi generano conteggi diversi per la stessa raccolta? Qualche idea su come ricaricare la raccolta o qualcosa su cui contare correttamente getSize()?
MagExt

ha aggiornato la voce
Fabian Blechschmidt

1
getSize()non carica la raccolta per i record che provengono dalla base di dati. A meno che non si ignori il metodo e gli dica di caricare la raccolta.
Marius

_totalRecords è protetto, quindi non posso chiamarlo nel mio file personalizzato con raccolta. echo count($collection->load()->getItems());dà il conteggio corretto, ma di nuovo voglio getSize()lavorare.
MagExt

5

Questa risposta appare su Google per "magento getSize wrong" e ricerche simili, quindi vorrei aggiungere un possibile scenario che potrebbe essere utile a qualcuno

Quando hai una dichiarazione di gruppo nella tua query e fai un

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

Mysql restituirà un conteggio per OGNI dei gruppi, quindi Varien_Data_Collection_Db :: getSize () restituirà la risposta sbagliata, questo perché questa funzione recupera la prima riga:

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

Quando si popola

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

Seleziona la prima riga e quindi restituisce il totale del primo gruppo come dimensione totale.

Ho finito con questo codice per contare, in base ai valori univoci degli attributi nella mia 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);

2

Nel caso in cui finissi qui, c'è un'altra soluzione semplice da provare:

System -> Index Management

e selezionali tutti (anche se indicano "Verde, non è necessario reindicizzare" e costringili a reindicizzare.

Ciò ha risolto il mio getSize()problema vuoto , che a sua volta ha permesso alle richieste di database speciali e nuove di trovare i prodotti, soddisfare le condizioni "if" e renderizzare correttamente.


0

Quando è count($collection)stato diverso dai $collection->getSize()miei reindexprodotti, tutto ha funzionato bene.


-1

C'è una differenza principale per getSize () la raccolta del prodotto non è caricata. Per count () caricherà l'intera raccolta di prodotti. Pertanto, per i grandi cataloghi non è consigliabile utilizzare la funzione di conteggio in nessuna raccolta.


Già detto in Marius post ...
sv3n
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.