Magento: il modo più veloce per aggiornare un attributo del prodotto


15

Sto cercando il metodo più rapido e affidabile per l'aggiornamento degli attributi di massa. Di seguito sono riportati i metodi di cui sono a conoscenza, ma non so con chi dovrei andare.

$store_id = 0;
Mage::getSingleton('catalog/product_action')->updateAttributes(
    array($product_id),
    array('attribute_code' => $attribute_code),
    $store_id
);

o

$product->setData($attribute_code, 1234); 
$product->getResource()->saveAttribute($product, $attribute_code); 

Risposte:


31

Il modo più veloce è effettuare selezioni e inserimenti / aggiornamenti diretti nel database, ma non è il più sicuro. Puoi facilmente rompere cose.

Uso l' Mage::getSingleton('catalog/product_action')->updateAttributes(...)approccio.
È veloce, puoi usarlo per aggiornare in blocco gli attributi del prodotto, puoi aggiornare un valore di attributo per un negozio specifico.
Penso che copra la maggior parte dei casi necessari.


grazie marius mi aspettavo la tua risposta, tra l'altro il tuo ultimo creatore di moduli è kool
Deepak Mallah,

1
in realtà non è la scelta più veloce ... controlla la mia risposta qui sotto
Fra

@Fra Come è il tuo metodo più veloce? Coinvolge load. che tutt'altro che veloce. Ad esempio, nel metodo 2, la prima riga con il carico del prodotto è inutile. Non stai usando da $productnessuna parte.
Marius

@Fra. Quando declassate la risposta di qualcuno, è una buona cosa dichiarare un motivo. Cosa c'è di sbagliato nella mia risposta?
Marius

1
Potrei dire la stessa cosa per la tua risposta ... non è il modo più veloce. le query SQL dirette sono il modo più veloce. Non credo che la tua ragione sia sufficiente per il downvoting. Ma hai diritto alla tua opinione.
Marius

27

In realtà ci sono 3 modi per aggiornare un attributo su un prodotto senza salvare l'intero prodotto. A seconda del codice / requisiti, uno può essere più veloce dell'altro.

Metodo 1:

$product = Mage::getModel('catalog/product')->load($product_id);
$resource = $product->getResource();

$product->setData($attribue_code, $value);
$resource->saveAttribute($product, $attribute_code);

Metodo 2:

$updater = Mage::getSingleton('catalog/product_action');
$updater->updateAttributes(array($product_id), array( $attribute_code => $value), 0);

Metodo 3: (più veloce)

 $update_resource = Mage::getResourceSingleton('catalog/product_action');
 $update_resource->updateAttributes(array($product_id), array( $attribute_code => $value), 0);

Tutti i metodi sopra indicati sono molto più veloci e consentono di salvare l'intero prodotto, tuttavia ci sono alcune importanti differenze di prestazioni:

Method 1:

  • è il più veloce, ma è necessario caricare il prodotto.
  • non attiva l'evento reindex (ecco perché è più veloce)
  • funziona in frontend

Method 2:

  • consente di aggiornare in blocco il prodotto
    (è possibile passare più prodotti e più attributi)
  • innesca l'evento di azione di massa e il relativo reindice dipendente
  • non funziona in frontend

Method 3:

  • è come il metodo 2, ma non chiama nessun altro osservatore / indicizzatore
    (quindi è un approccio misto tra il metodo 1 e 2)

Il metodo 3 è comunque il più flessibile che dovrai reindicizzare manualmente tali prodotti / attributi. (per aggiornarli sul frontend)
Può essere utile se vuoi aggiornare molti prodotti velocemente e chiamare il reindex alla fine.
(se si utilizza il metodo 2, dopo l'aggiornamento viene chiamato un reindex per ciascun prodotto e queste chiamate multiple rallentano l'intero processo)

Per reindicizzare manualmente un singolo prodotto, vedere le funzioni fornite da Mage_Catalog_Model_Product_Flat_Indexer come:

  • updateAttribute($attributeCode, $store = null, $productIds = null)
  • updateProduct($productIds, $store = null)
  • ...

4
sarebbe sempre meglio commentare il voto negativo ...
Fra

Solo una piccola nota, il valore $ dovrebbe essere un codice valore (intero), non il valore "testuale" che vedi nell'interfaccia
Ali Alwash,

hmmm interessante. Il metodo 2 suona alla grande, solo tu non hai controllo sul "feedback" che cosa è riuscito, cosa no? Anche il metodo 1 è buono. Ma quando avrò finito di aggiornare il mio loop over data: posso avviare manualmente il reindex forse per risolverlo per particolari ID prodotto?
snh_nl,

Strano. utilizzando il metodo 2. Ricevo un errore di filtro sconosciuto per colonna `` Eccezione rilevata: SQLSTATE [42S22]: Colonna non trovata: 1054 Colonna sconosciuta 'catalog_product_entity.value_id' in 'elenco campi', la query era: SELEZIONA catalog_product_entity. value_idDA catalog_product_entityDOVE (entity_type_id = 4 AND attributo_id = '68 'AND entity_id = '29') `` `non me l'aspettavo. In esecuzione il 1.9.3.2
snh_nl il

1
Mi ha salvato ore di lavoro.
dipole_moment,

3

Aggiornare

Sto cercando il metodo più rapido e affidabile per l'aggiornamento degli attributi di massa

"Aggiornamento degli attributi di massa" per attributi o prodotti?

Pensa che sia sempre stata data risposta all'aggiornamento di più attributi, ma per i prodotti questo può essere utile ...

Se desideri aggiornare i prodotti dalla raccolta, non dovresti farlo ...

foreach ($collection as $product) {
    $product->setSomeData(...);
    # not here
    $product->save();
}

Questo invierà eventi, ricostruirà pricerules e indici. Con questo nessun evento (e alcune altre cose) vengono saltati ed è molto più veloce.

foreach ($collection as $product) {
    $product->setSomeData(...);
}
$collection->save();

Per evitare gli aggiornamenti dei pricerule, puoi aggiungere ...

$product->setIsMassupdate(true);

Per disabilitare / abilitare reindex al volo dai un'occhiata a questo ... https://github.com/Flagbit/Magento-ChangeAttributeSet/commit/676f3af77fec880bc64333403675d183e8639fae

/**
 * Set indexer modes to manual
 */
private function _storeRealtimeIndexer()
{
    $collection = Mage::getSingleton('index/indexer')->getProcessesCollection();
    foreach ($collection as $process) {
        if($process->getMode() != Mage_Index_Model_Process::MODE_MANUAL){
            $this->_index[] = $process->getIndexerCode();
            $process->setData('mode', Mage_Index_Model_Process::MODE_MANUAL)->save();
        }
    }

}
/**
 * Restore indexer modes to realtime an reindex product data
 */
private function _restoreRealtimeIndexer()
{
    $reindexCodes = array(
        'catalog_product_attribute',
        'catalog_product_flat'
    );
    $indexer = Mage::getSingleton('index/indexer');
    foreach ($this->_index as $code) {
        $process = $indexer->getProcessByCode($code);
        if (in_array($code, $reindexCodes)) {
            $process->reindexAll();
        }
        $process->setData('mode', Mage_Index_Model_Process::MODE_REAL_TIME)->save();
    }
}

E anche lo svuotamento della cache prima dell'aggiornamento di massa (prodotto) può aumentare le prestazioni ...

Mage::app()->getCacheInstance()->flush();

Alcuni numeri dal debug qui: https://github.com/Flagbit/Magento-ChangeAttributeSet/issues/16


Mage::getSingleton('catalog/product_action')->updateAttributes(...) sembra non essere il metodo più veloce ... almeno non con l'installazione di mutlistore e le tabelle piatte attivate ...

  • saveAttribute()

    $product = Mage::getModel('catalog/product')->load($productId);
    $resource = $product->getResource();
    $product->setData($attributeCode, $attributeValue);
    $resource->saveAttribute($product, $attributeCode);
    • Totale incl. Wall Time (microsec): 437.787 microsec
    • Totale incl. CPU (microsec): 423.600 microsec
    • Totale incl. MemUse (byte): 4.433.848 byte
    • Totale incl. PeakMemUse (byte): 4.395.128 byte
    • Numero di chiamate di funzione: 25.711
  • updateAttributes()

    Mage::getSingleton('catalog/product_action')->updateAttributes(
        array($productId),
        array($attributeCode => $attributeValue),
        $storeId
    );
    • Totale incl. Wall Time (microsec): 3.676.950 microsec
    • Totale incl. CPU (microsec): 3.122.064 microsec
    • Totale incl. MemUse (byte): 8.174.792 byte
    • Totale incl. PeakMemUse (byte): 8.199.192 byte
    • Numero di chiamate di funzione: 150.132
  • updateAttributes() (risorsa singleton)

    Mage::getResourceSingleton('catalog/product_action')->updateAttributes(
        array($productId),
        array( $attributeCode => $attributeValue),
        $storeId
    );
    • Totale incl. Wall Time (microsec): 94.155 microsecs
    • Totale incl. CPU (microsec): 48.568 microsec
    • Totale incl. MemUse (byte): 1.426.304 byte
    • Totale incl. PeakMemUse (byte): 1.370.456 byte
    • Numero di chiamate di funzione: 2.221

puoi rivedere la mia risposta per capire perché queste funzioni richiedono tempi diversi ...
Fra

Per i dati a discesa updateAttributes() (resource singleton)prende il valore di amministratore effettivo? o l'id dell'elemento a discesa? (in qualche modo non otteniamo sempre alcun valore / valore vuoto usando questo metodo, cioè niente di selezionato
snh_nl

@snh_nl devi usare l'ID - virgola separata per gli attributi a selezione multipla.
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.