Индексирование в magento

Post on 22-May-2015

4.278 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Индексация в Magento

Виктор ТихончукMagento System Architect

Модуль Mage_Index

События

Индекс

Индексатор

Процесс

Событие

Mage_Index_Model_Event

Событие – то, что происходит в некоторый момент времени и рассматривается как изменение состояния сущности.

Событие хранит информацию о сущности, с которой произошло действие и тип действия.

Типы изменений сущности (event type)• Сохранение (SAVE)

• Удаление (DELETE)

• Групповая обработка (MASS_ACTION)

Обработчик

Mage_Index_Model_Indexer

• processEntityAction($entity, $entityType, $eventType)

• logEvent($entity, $entityType, $eventType)

• registerEvent(Mage_Index_Model_Event $event)

• indexEvent(Mage_Index_Model_Event $event)

• indexEvents($entity = null, $type = null)

Изменения в абстрактной модели

Процесс сохранения• _getResource()->beginTransaction()

• _beforeSave()

• _getResource()->save()

• _afterSave()

• _getResource()->commit()

• afterCommitCallback()

Новые события• model_save_commit_after

• {eventPrefix}_save_commit_after

Изменения в абстрактной модели

Процесс удаления• _getResource()->beginTransaction()

• _beforeDelete()

• _getResource()->delete()

• _afterDelete()

• _getResource()->commit()

• _afterDeleteCommit()

Новые события• model_delete_commit_after

• {eventPrefix}_delete_commit_after

Сущности

• catalog/product (SAVE, DELETE, MASS_ACTION)

• catalog/category (SAVE, DELETE)

• catalog/resource_eav_attribute (SAVE, DELETE)

• customer/group (SAVE)

• cataloginventory/stock_item (SAVE)

• tag/tag (SAVE)

• core/store (SAVE, DELETE)

• core/store_group (SAVE, DELETE)

• core/website (SAVE, DELETE)

Процессы и индексаторы

Индексатор может работать в 2х режимах:

• в режиме реального времени (MODE_REAL_TIME)

• в ручном режиме (MODE_MANUAL)

У каждого индексатора есть текущий статус:

• работает (STATUS_RUNNING)

• режим ожидания (STATUS_PENDING)

• необходимо перестроить (STATUS_REQUIRE_REINDEX)

REQUIRE_REINDEXMODE MANUAL

New Indexer

Событие

Процесс

Mage_Index_Model_Process

• matchEvent(Mage_Index_Model_Event $event)

• register(Mage_Index_Model_Event $event)

• processEvent(Mage_Index_Model_Event $event)

• reindexAll()

• reindexEverything()

• indexEvents()

• changeStatus($status)

• getIndexer()

CatalogInventory Stock Status

Цель оптимизировать затраты на подсчет возможности

покупки товара при отображении товаров в каталоге, поиске и т.д.

Мотивация для простых (simple) товаров - динамически определить

доступность не является трудозатратной операцией, чего не скажешь о составных (composite), для которых нужно учитывать статус всех его составляющих

Задача сделать предварительно подсчитанный статус для

каждого товара с учетом склада и веб сайта

Шаг 1: Структура данных индекса

cataloginventory/stock_status

product_id

website_id

stock_id

qty

stock_status

Шаг 2: Создаем индексатор

Mage_CatalogInventory_Model_Indexer_Stock

Шаг 2: Создаем индексатор

Mage_CatalogInventory_Model_Indexer_Stock

Mage_Index_Model_Indexer_Abstract

Шаг 2: Создаем индексатор

Mage_CatalogInventory_Model_Indexer_Stock

Mage_Core_Model_Abstract

Mage_Index_Model_Indexer_Abstract

Шаг 2: Создаем индексатор

Mage_CatalogInventory_Model_Mysql4_Indexer_Stock

Mage_Core_Model_Mysql4_Abstract

Mage_Index_Model_Mysql4_Indexer_Abstract

Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Indexer_Abstract

Шаг 2: Создаем индексатор

Абстрактные методы индексатора• getName()

• getDescription()

• _registerEvent()

• _processEvent()

Шаг 3: Событияprotected $_matchedEntities = array(    Mage_CatalogInventory_Model_Stock_Item::ENTITY => array(        Mage_Index_Model_Event::TYPE_SAVE    ),    Mage_Catalog_Model_Product::ENTITY => array(        Mage_Index_Model_Event::TYPE_SAVE,        Mage_Index_Model_Event::TYPE_MASS_ACTION,        Mage_Index_Model_Event::TYPE_DELETE    ),    Mage_Core_Model_Store::ENTITY => array(        Mage_Index_Model_Event::TYPE_SAVE    ),    Mage_Core_Model_Store_Group::ENTITY => array(        Mage_Index_Model_Event::TYPE_SAVE    ),    Mage_Core_Model_Config_Data::ENTITY => array(        Mage_Index_Model_Event::TYPE_SAVE    ),    Mage_Catalog_Model_Convert_Adapter_Product::ENTITY => array(        Mage_Index_Model_Event::TYPE_SAVE    ));

Шаг 4: Изменение конфигурацииprotected $_relatedConfigSettings = array(    Mage_CatalogInventory_Model_Stock_Item::XML_PATH_MANAGE_STOCK,    Mage_CatalogInventory_Helper_Data::XML_PATH_SHOW_OUT_OF_STOCK);

public function matchEvent(Mage_Index_Model_Event $event){ // check saved result in $event and return it if ($entity == Mage_Core_Model_Config_Data::ENTITY) { $configData = $event->getDataObject(); $path = $configData->getPath(); if (in_array($path, $this->_relatedConfigSettings)) { $result = $configData->isValueChanged(); } else { $result = false; } } else { $result = parent::matchEvent($event); } // save result in $event and return it}

Шаг 5: Регистрация событияprotected function _registerEvent(Mage_Index_Model_Event $event){    switch ($event->getEntity()) {        case Mage_Catalog_Model_Product::ENTITY:            $this->_registerCatalogProductEvent($event);            break;  // skip some cases        case Mage_Core_Model_Store::ENTITY:        case Mage_Core_Model_Config_Data::ENTITY: $reindex = Mage_Index_Model_Process::STATUS_REQUIRE_REINDEX;            $event->addNewData('skip_call_event_handler', true);            $process = $event->getProcess();            $process->changeStatus($reindex);             if ($event->getEntity() == Mage_Core_Model_Config_Data::ENTITY) {                $configData = $event->getDataObject(); $indexer = Mage::getSingleton('index/indexer');                if ($configData->getPath() == XML_PATH_SHOW_OUT_OF_STOCK) {                    $index->getProcessByCode('catalog_product_price')                        ->changeStatus($reindex);                    $indexer->getProcessByCode('catalog_product_attribute')                        ->changeStatus($reindex);                }            }            break;    }}

Шаг 5: Регистрация событияprotected function _registerCatalogProductDeleteEvent (Mage_Index_Model_Event $event){    /** @var $product Mage_Catalog_Model_Product */    $product = $event->getDataObject();     $parentIds = $this->_getResource() ->getProductParentsByChild($product->getId());    if ($parentIds) {        $event->addNewData('reindex_stock_parent_ids', $parentIds);    }     return $this;}

Шаг 6: Обработка событияprotected function _processEvent(Mage_Index_Model_Event $event){ $data = $event->getNewData(); if (!empty($data['cataloginventory_stock_reindex_all'])) { $this->reindexAll(); } if (empty($data['skip_call_event_handler'])) { $this->callEventHandler($event); }}

Шаг 7: Ресурс модель

Resource Model

Type Indexer Interface

Type Indexer Default

Type Indexer Configurable

Шаг 7: Ресурс модель protected function _getTypeIndexers() { if (is_null($this->_indexers)) { $this->_indexers = array(); $types = Mage::getSingleton('catalog/product_type') ->getTypesByPriority(); foreach ($types as $typeId => $typeInfo) { if (isset($typeInfo['stock_indexer'])) { $modelName = $typeInfo['stock_indexer']; } else { $modelName = $this->_defaultIndexer; } $isComposite = !empty($typeInfo['composite']); $indexer = Mage::getResourceModel($modelName) ->setTypeId($typeId) ->setIsComposite($isComposite);

$this->_indexers[$typeId] = $indexer; } } return $this->_indexers; }

Шаг 7: Ресурс модель public function reindexAll() { $this->useIdxTable(true); $this->clearTemporaryIndexTable();

foreach ($this->_getTypeIndexers() as $indexer) { $indexer->reindexAll(); }

$this->syncData(); return $this; }

Шаг 7: Ресурс модель public function catalogProductDelete(Mage_Index_Model_Event $event) { $data = $event->getNewData(); if (empty($data['reindex_stock_parent_ids'])) { return $this; }

$adapter = $this->_getWriteAdapter();

$parentIds = array(); foreach ($data['reindex_stock_parent_ids'] as $parentId => $parentType) { $parentIds[$parentType][$parentId] = $parentId; }

$adapter->beginTransaction(); try { foreach ($parentIds as $parentType => $entityIds) { $this->_getIndexer($parentType)->reindexEntity($entityIds); } } catch (Exception $e) { $adapter->rollback(); throw $e; }

$adapter->commit();

return $this; }

Шаг 8: Ресурс модели (TYPE Default) public function setTypeId($typeId) { $this->_typeId = $typeId; return $this; }

public function getTypeId() { if (is_null($this->_typeId)) { Mage::throwException(Mage::helper('cataloginventory') ->__('Undefined product type.')); } return $this->_typeId; } public function reindexAll() { $this->useIdxTable(true); $this->_prepareIndexTable(); return $this; } public function reindexEntity($entityIds) { $this->_updateIndex($entityIds); return $this; }

Шаг 9: Декларация индексатора<config> <!-- ... --> <global> <!-- ... --> <index> <indexer> <cataloginventory_stock> <model>cataloginventory/indexer_stock</model> </cataloginventory_stock> <catalog_product_attribute> <depends> <cataloginventory_stock /> </depends> </catalog_product_attribute> <catalog_product_price> <depends> <cataloginventory_stock /> </depends> </catalog_product_price> </indexer> </index> </global></config>

Индекс цен для B2B

Цель Создать новый тип товара B2B

Справка В2В – сокращение от английских слов «business to business»,

в буквальном переводе – бизнес для бизнеса. Это сектор рынка, который работает не на конечного, рядового потребителя, а на такие же компании, то есть на другой бизнес.

Задача Новый тип товара, который наследует поведение простого

товара (simple), но имеет возможность указать цену для каждой группы пользователей (customer group)

Индекс цен для B2B

public function reindexAll();public function reindexEntity($entityIds);public function registerEvent(Mage_Index_Model_Event $event);

Знакомство с интерфейсом Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Indexer_Price_Interface

Создаем свой индексатор

class Mageconf_B2b_Model_Mysql4_Indexer_Price extends Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Indexer_Price_Default{}

Индекс цен для B2B

public function reindexAll(){ $this->useIdxTable(true); $this->_prepareFinalPriceData(); $this->_applyCustomOption(); $this->_movePriceDataToIndexTable(); return $this;}

public function reindexEntity($entityIds){ $this->_prepareFinalPriceData($entityIds); $this->_applyCustomOption(); $this->_movePriceDataToIndexTable();

return $this;}

Знакомство с … Indexer_Price_Default

Индекс цен для B2B

protected function _getDefaultFinalPriceTable(){ if ($this->useIdxTable()) { return $this->getTable('catalog/product_price_indexer_final_idx'); } return $this->getTable('catalog/product_price_indexer_final_tmp');}

Индекс цен для B2Bcatalog/product_price_indexer_final_*

entity_id

customer_group_id

website_id

tax_class_id

orig_price

price

min_price

max_price

tier_price

base_tier

Индекс цен для B2Bprotected function _prepareFinalPriceData($entityIds = null){ // удаляем данные из таблицы, если они есть $this->_prepareDefaultFinalPriceTable();

$write = $this->_getWriteAdapter(); $select = $write->select() ->from(array('e' => $this->getTable('catalog/product')), array('entity_id')) ->joinCross( array('cg' => $this->getTable('customer/customer_group')), array('customer_group_id')) ->joinCross( array('cw' => $this->getTable('core/website')), array('website_id')) ->join( array('cwd' => $this->_getWebsiteDateTable()), 'cw.website_id = cwd.website_id', array()) ->join( array('csg' => $this->getTable('core/store_group')), 'csg.website_id = cw.website_id AND cw.default_group_id = csg.group_id', array()) ->join( array('cs' => $this->getTable('core/store')), 'csg.default_store_id = cs.store_id AND cs.store_id != 0', array()); // next slide

Индекс цен для B2B // protected function _prepareFinalPriceData($entityIds = null) $select ->join( array('pw' => $this->getTable('catalog/product_website')), 'pw.product_id = e.entity_id AND pw.website_id = cw.website_id', array()) ->joinLeft( array('tp' => $this->_getTierPriceIndexTable()), 'tp.entity_id = e.entity_id AND tp.website_id = cw.website_id' . ' AND tp.customer_group_id = cg.customer_group_id', array()) ->join( array('b2d' => $this->getTable('b2b/price')), 'b2d.entity_id = e.entity_id AND b2d.customer IS NULL AND website_id=0' array()) ->join( array('b2w' => $this->getTable('b2b/price')), 'b2w.entity_id = e.entity_id AND b2w.customer = cg.customer_group_id' . ' AND b2w.website_id = cw.website_id', array()) ->where('e.type_id=?', $this->getTypeId());

$statusCond = $write->quoteInto('=?', Mage_Catalog_Model_Product_Status::STATUS_ENABLED); $this->_addAttributeToSelect($select, 'status', 'e.entity_id', 'cs.store_id', $statusCond, true);

Индекс цен для B2B // protected function _prepareFinalPriceData($entityIds = null)

$taxClassId = $this->_addAttributeToSelect($select, 'tax_class_id', 'e.entity_id', 'cs.store_id'); $select->columns(array('tax_class_id' => $taxClassId));

$finalPrice = new Zend_Db_Expr('IFNULL(b2w.price, b2d.price)');

$select->columns(array( 'orig_price' => $price, 'price' => $finalPrice, 'min_price' => $finalPrice, 'max_price' => $finalPrice, 'tier_price' => new Zend_Db_Expr('NULL'), 'base_tier' => new Zend_Db_Expr('NULL'), ));

if (!is_null($entityIds)) { $select->where('e.entity_id IN(?)', $entityIds); }

Индекс цен для B2B // protected function _prepareFinalPriceData($entityIds = null)

Mage::dispatchEvent('prepare_catalog_product_index_select', array( 'select' => $select, 'entity_field' => new Zend_Db_Expr('e.entity_id'), 'website_field' => new Zend_Db_Expr('cw.website_id'), 'store_field' => new Zend_Db_Expr('cs.store_id') ));

$query = $select->insertromSelect($this->_getDefaultFinalPriceTable()); $write->query($query);

return $this;}

public function registerEvent(Mage_Index_Model_Event $event){ $entity = $event->getEntity(); if ($entity == Mage_Catalog_Model_Product::ENTITY) { if ($event->getType() == Mage_Index_Model_Event::TYPE_SAVE) { // check attributes // add data to event } }}

Обзор индексаторов в Magento

• Product Attributes

• Product Prices

• Catalog URL Rewrites

• Product Flat Data

• Category Flat Data

• Category Products

• Catalog Search Index

• Stock Status

• Tag Aggregation Data

Спасибо за вниманиеEmail: victor@magento.com

top related