Magento: la forma más rápida de actualizar un atributo de producto

15

Estoy buscando el método más rápido y confiable para la actualización masiva de atributos. A continuación se detallan los métodos que conozco pero no sé con qué debo ir.

$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); 
Deepak Mallah
fuente

Respuestas:

31

La forma más rápida es hacer selecciones directas e insertar / actualizar en la base de datos, pero eso no es lo más seguro. Puedes romper cosas fácilmente.

Yo uso el Mage::getSingleton('catalog/product_action')->updateAttributes(...)enfoque.
Es rápido, puede usarlo para actualizar en masa los atributos del producto, puede actualizar el valor de un atributo para una tienda específica.
Creo que cubre la mayoría de los casos necesarios.

Marius
fuente
gracias marius, esperaba tu respuesta, por cierto, tu creador de módulo final es kool
Deepak Mallah
1
en realidad no es la opción más rápida ... verifique mi respuesta a continuación
Fra
@Fra ¿Cómo es tu método más rápido? Implica load. que cualquier cosa menos rápido Por ejemplo, en el método 2, la primera línea con la carga del producto es inútil. No estás usando en $productningún lado.
Marius
@Fra. Cuando rechazas la respuesta de alguien, es bueno decir una razón. ¿Qué hay de malo en mi respuesta?
Marius
1
Podría decir lo mismo para su respuesta ... no es la forma más rápida. Las consultas directas de SQL son la forma más rápida. No creo que tu razón sea suficiente para votar negativamente. Pero tienes derecho a tu opinión.
Marius
27

En realidad, hay 3 formas de actualizar un atributo en un producto sin guardar el producto completo. Dependiendo del código / requisitos, uno puede ser más rápido que el otro.

Método 1:

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

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

Método 2:

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

Método 3: (más rápido)

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

Todos los métodos anteriores son mucho más rápidos y ahorran todo el producto de todos modos, existen algunas diferencias importantes de rendimiento:

Method 1:

  • es el más rápido, pero requiere que cargues el producto.
  • no desencadena el evento reindex (es por eso que es más rápido)
  • funciona en frontend

Method 2:

  • permite la actualización masiva de productos
    (puede pasar múltiples productos y múltiples atributos)
  • desencadena el evento de acción masiva y el reindex dependiente relativo
  • no funciona en frontend

Method 3:

  • es como el método 2, pero no llama a ningún otro observador / indexador
    (por lo que es un enfoque mixto entre el método 1 y el 2)

El método 3 es el más flexible de todos modos, tendrá que reindexar esos productos / atributos manualmente. (para actualizarlos en la interfaz)
Puede ser útil si desea actualizar muchos productos rápidamente y luego llamar al reindex al final.
(si usa el método 2, se llama a un reindex para cada producto después de la actualización y estas llamadas múltiples hacen que todo el proceso sea lento)

Para reindexar manualmente un solo producto, consulte las funciones proporcionadas por Mage_Catalog_Model_Product_Flat_Indexer como:

  • updateAttribute($attributeCode, $store = null, $productIds = null)
  • updateProduct($productIds, $store = null)
  • ...
Fra
fuente
44
siempre sería mejor hacer un comentario negativo ...
Fra
Solo una pequeña nota, el valor de $ debe ser un código de valor (entero), no el valor 'textual' que ves en tu interfaz
Ali Alwash, el
hmmm interesante. El método 2 suena muy bien, solo que usted no tiene control sobre la 'retroalimentación' que tuvo éxito y que no. El método 1 también es bueno. Pero cuando termine de actualizar mi ciclo sobre los datos: ¿puedo patear manualmente el reindex tal vez para resolver esto para identificadores de productos particulares?
snh_nl
Extraño. usando el Método 2. Recibo un error de filtro desconocido por columna `` `Excepción atrapada: SQLSTATE [42S22]: Columna no encontrada: 1054 Columna desconocida 'catalog_product_entity.value_id' en 'lista de campos', la consulta fue: SELECCIONAR catalog_product_entity. value_idDESDE catalog_product_entityDONDE (entity_type_id = 4 AND attribute_id = '68 'AND entity_id = '29') `` `no esperaba eso. Se ejecuta en 1.9.3.2
snh_nl
1
Me ahorró horas de trabajo.
dipole_moment
3

Actualizar

Estoy buscando el método más rápido y confiable para la actualización masiva de atributos

¿"Actualización masiva de atributos" para atributos o productos?

Piense que la actualización de múltiples atributos ya está respondida, pero para los productos esto puede ser útil ...

Si desea actualizar productos de la colección, no debe hacer esto ...

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

Esto enviará eventos, reconstruirá precios e índices. Con esto no se omiten eventos (y algunas otras cosas) y es mucho más rápido.

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

Para evitar actualizaciones de precios, puede agregar ...

$product->setIsMassupdate(true);

Para deshabilitar / habilitar reindex sobre la marcha, eche un vistazo a esto ... 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();
    }
}

Y también vaciar el caché antes de la actualización masiva (producto) puede aumentar el rendimiento ...

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

Algunos números de depuración aquí: https://github.com/Flagbit/Magento-ChangeAttributeSet/issues/16


Mage::getSingleton('catalog/product_action')->updateAttributes(...) parece que no es el método más rápido ... al menos no con la configuración de mutlistore y las tablas planas activadas ...

  • saveAttribute()

    $product = Mage::getModel('catalog/product')->load($productId);
    $resource = $product->getResource();
    $product->setData($attributeCode, $attributeValue);
    $resource->saveAttribute($product, $attributeCode);
    • Total incl. Tiempo de pared (microsec): 437,787 microsecs
    • Total incl. CPU (microsecs): 423,600 microsecs
    • Total incl. MemUse (bytes): 4,433,848 bytes
    • Total incl. PeakMemUse (bytes): 4,395,128 bytes
    • Número de llamadas a funciones: 25,711
  • updateAttributes()

    Mage::getSingleton('catalog/product_action')->updateAttributes(
        array($productId),
        array($attributeCode => $attributeValue),
        $storeId
    );
    • Total incl. Tiempo de pared (microsec): 3,676,950 microsecs
    • Total incl. CPU (microsecs): 3,122,064 microsecs
    • Total incl. MemUse (bytes): 8,174,792 bytes
    • Total incl. PeakMemUse (bytes): 8,199,192 bytes
    • Número de llamadas a funciones: 150,132
  • updateAttributes() (recurso singleton)

    Mage::getResourceSingleton('catalog/product_action')->updateAttributes(
        array($productId),
        array( $attributeCode => $attributeValue),
        $storeId
    );
    • Total incl. Tiempo de pared (microsec): 94,155 microsecs
    • Total incl. CPU (microsecs): 48,568 microsecs
    • Total incl. MemUse (bytes): 1,426,304 bytes
    • Total incl. PeakMemUse (bytes): 1,370,456 bytes
    • Número de llamadas a funciones: 2,221
sv3n
fuente
puede revisar mi respuesta para entender por qué esas funciones toman diferentes tiempos ...
Fra
Para los datos desplegables, ¿ updateAttributes() (resource singleton)toma el valor de administrador real? o la identificación del elemento desplegable? (de alguna manera siempre no obtenemos ningún valor / valor vacío usando este método, es decir, nada seleccionado
snh_nl
@snh_nl tiene que usar la ID: coma separada para los atributos de selección múltiple.
sv3n