Magento: le moyen le plus rapide de mettre à jour un attribut de produit

15

Je recherche la méthode la plus rapide et fiable pour la mise à jour des attributs de masse. Voici les méthodes que je connais, mais je ne sais pas avec quoi je dois aller.

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

ou

$product->setData($attribute_code, 1234); 
$product->getResource()->saveAttribute($product, $attribute_code); 
Deepak Mallah
la source

Réponses:

31

Le moyen le plus rapide consiste à effectuer des sélections directes et des insertions / mises à jour dans la base de données, mais ce n'est pas le plus sûr. Vous pouvez facilement casser des trucs.

J'utilise l' Mage::getSingleton('catalog/product_action')->updateAttributes(...)approche.
C'est rapide, vous pouvez l'utiliser pour mettre à jour en masse les attributs du produit, vous pouvez mettre à jour une valeur d'attribut pour un magasin spécifique.
Je pense que cela couvre la plupart des cas nécessaires.

Marius
la source
merci marius j'attendais votre réponse, btw votre créateur de module ultime est kool
Deepak Mallah
1
ce n'est pas vraiment le choix le plus rapide ... vérifiez ma réponse ci
Fra
@Fra Comment votre méthode est-elle plus rapide? Cela implique load. que tout sauf rapide. Par exemple, dans la méthode 2, la première ligne avec la charge de produit est inutile. Vous n'utilisez $productnulle part.
Marius
@Fra. Lorsque vous dévaluez la réponse de quelqu'un, c'est une bonne chose de dire une raison. Quel est le problème avec ma réponse?
Marius
1
Je pourrais dire la même chose pour votre réponse ... ce n'est pas le moyen le plus rapide. les requêtes SQL directes sont le moyen le plus rapide. Je ne pense pas que votre raison soit suffisante pour voter en aval. Mais vous avez droit à votre opinion.
Marius
27

En fait, il existe 3 façons de mettre à jour un attribut sur un produit sans enregistrer le produit complet. Selon le code / les exigences, l'un peut être plus rapide que l'autre.

Méthode 1:

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

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

Méthode 2:

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

Méthode 3: (la plus rapide)

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

Toutes les méthodes ci-dessus sont beaucoup plus rapides et permettent d'économiser le produit dans son intégralité.

Method 1:

  • est le plus rapide, mais vous a demandé de charger le produit.
  • il ne déclenche pas l'événement de réindexation (c'est pourquoi est plus rapide)
  • ça marche en frontend

Method 2:

  • permet de mettre à jour le produit en masse
    (vous pouvez passer plusieurs produits et plusieurs attributs)
  • il déclenche l'événement d'action de masse et la réindexation dépendante relative
  • ça ne marche pas en frontend

Method 3:

  • c'est comme la méthode 2, mais n'appelle aucun autre observateur / indexeur
    (c'est donc une approche mixte entre la méthode 1 et 2)

La méthode 3 est la plus flexible de toute façon, vous devrez réindexer manuellement ces produits / attributs. (afin de les mettre à jour sur le frontend)
Il peut être utile de mettre à jour rapidement un grand nombre de produits, puis d'appeler la réindexation à la fin.
(si vous utilisez la méthode 2, une réindexation pour chaque produit est appelée après la mise à jour et ces multiples appels ralentissent l'ensemble du processus)

Pour réindexer manuellement un seul produit, voir les fonctions fournies par Mage_Catalog_Model_Product_Flat_Indexer telles que:

  • updateAttribute($attributeCode, $store = null, $productIds = null)
  • updateProduct($productIds, $store = null)
  • ...
Fra
la source
4
il serait toujours préférable de commenter downvote ...
Fra
Juste une petite note, la valeur $ doit être un code de valeur (entier), pas la valeur 'textuelle' que vous voyez dans votre interface
Ali Alwash
hmmm intéressant. La méthode 2 sonne bien, seulement vous n'avez aucun contrôle sur le «feedback» ce qui a réussi, qu'est-ce qui n'a pas réussi? La méthode 1 est également bonne. Mais lorsque j'ai terminé de mettre à jour ma boucle sur les données: puis-je lancer manuellement la réindexation peut-être pour résoudre ce problème pour les ID de produit particuliers?
snh_nl
Étrange. en utilisant la méthode 2. Je reçois un filtre d'erreur inconnu par la colonne `` `Exception détectée: SQLSTATE [42S22]: Colonne introuvable: 1054 Colonne inconnue 'catalog_product_entity.value_id' dans la 'liste des champs', la requête était: SELECT catalog_product_entity. value_idDEPUIS catalog_product_entityO ((entity_type_id = 4 AND attribute_id = '68 'AND entity_id = '29') `` ne s'y attendait pas. En cours d'exécution le 1.9.3.2
snh_nl
1
M'a sauvé des heures de travail.
dipole_moment
3

Mise à jour

Je recherche la méthode la plus rapide et fiable pour la mise à jour des attributs de masse

"Mise à jour massive des attributs" pour les attributs ou les produits?

Pensez à mettre à jour plusieurs attributs est déjà répondu, mais pour les produits, cela peut être utile ...

Si vous souhaitez mettre à jour des produits de la collection, vous ne devriez pas le faire ...

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

Cela enverra les événements, reconstruira les prix et les indices. Avec cela, aucun événement (et d'autres choses) n'est ignoré et est beaucoup plus rapide.

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

Pour éviter les mises à jour de prix, vous pouvez ajouter ...

$product->setIsMassupdate(true);

Pour désactiver / activer la réindexation à la volée, jetez un œil à ceci ... 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();
    }
}

Et vider le cache avant la mise à jour en masse (produit) peut augmenter les performances ...

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

Quelques chiffres du débogage ici: https://github.com/Flagbit/Magento-ChangeAttributeSet/issues/16


Mage::getSingleton('catalog/product_action')->updateAttributes(...) ne semble pas être la méthode la plus rapide ... du moins pas avec la configuration mutlistore et les tables plates activées ...

  • saveAttribute()

    $product = Mage::getModel('catalog/product')->load($productId);
    $resource = $product->getResource();
    $product->setData($attributeCode, $attributeValue);
    $resource->saveAttribute($product, $attributeCode);
    • Total incl. Temps de mur (microsec): 437,787 microsecs
    • Total incl. CPU (microsecs): 423 600 microsecs
    • Total incl. MemUse (octets): 4 433 848 octets
    • Total incl. PeakMemUse (octets): 4 395 128 octets
    • Nombre d'appels de fonction: 25 711
  • updateAttributes()

    Mage::getSingleton('catalog/product_action')->updateAttributes(
        array($productId),
        array($attributeCode => $attributeValue),
        $storeId
    );
    • Total incl. Temps de paroi (microsec): 3,676,950 microsecs
    • Total incl. CPU (microsecs): 3,122,064 microsecs
    • Total incl. MemUse (octets): 8,174,792 octets
    • Total incl. PeakMemUse (octets): 8 199 192 octets
    • Nombre d'appels de fonction: 150 132
  • updateAttributes() (ressource singleton)

    Mage::getResourceSingleton('catalog/product_action')->updateAttributes(
        array($productId),
        array( $attributeCode => $attributeValue),
        $storeId
    );
    • Total incl. Durée du mur (microsecondes): 94 155 microsecondes
    • Total incl. CPU (microsecs): 48,568 microsecs
    • Total incl. MemUse (octets): 1 426 304 octets
    • Total incl. PeakMemUse (octets): 1 370 456 octets
    • Nombre d'appels de fonction: 2 221
sv3n
la source
vous pouvez revoir ma réponse pour comprendre pourquoi ces fonctions prennent des temps différents ...
Fra
Pour les données déroulantes updateAttributes() (resource singleton)prend la valeur admin réelle? ou l'id de l'élément déroulant? (en quelque sorte, nous n'obtenons toujours aucune valeur / valeur vide en utilisant cette méthode, c'est-à-dire rien sélectionné
snh_nl
@snh_nl vous devez utiliser l'ID - virgule séparée pour les attributs multisélectionnés.
sv3n