Magento-Suche

Problem: In the Magento search, a search for "Ölen" returns products from Poland, a search for "grün" returns all kinds of primers, and a search for "Laser" returns all glasses in the shop.

A search for "Bio Honig" also returns "Bio Tofu", while "Haar Gel" returns white beer jelly. If you do not want to switch to the full-text search in order to keep the potential for errors low, refining Magento's standard search function is a good option:
With the search setting "Combine (Like and Fulltext)" and extending two resource models, a basic improvement can already be achieved:

Step 1: Create a module, using the namespace "Econcess" and module name "EconSearch" as an example. The module consists of only 3 files (\app\code\local\Econcess\EconSearch\etc\config.xml, \app\code\local\Econcess\EconSearch\Model\Resource\Query.php and \app\code\local\Econcess\EconSearch\Model\Resource\Fulltext.php) and is registered with Magento using \app\etc\modules\Econcess_EconSearch.xml.

Contents of \app\etc\modules\Econcess_EconSearch.xml:


<config>
<modules>
<Econcess_EconSearch>
<active>true</active>
<codePool>local</codePool>
</Econcess_EconSearch>
</modules>
</config>

Contents of \app\code\local\Econcess\EconSearch\etc\config.xml:

<?xml version="1.0"?>
<config>
<modules>
<Econcess_EconSearch>
<version>1.0.0</version>
</Econcess_EconSearch>
</modules>
<global>
<models>
<econsearch>
<class>Mage_CatalogSearch_Model</class>
</econsearch>
<catalogsearch_resource>
<class>Mage_CatalogSearch_Model_Resource</class>
<rewrite>
<fulltext>Econcess_EconSearch_Model_Resource_Fulltext</fulltext>
<query>Econcess_EconSearch_Model_Resource_Query</query>
</rewrite>
</catalogsearch_resource>
</models>
</global>
</config>

This means that only 2 resource models are overridden or extended.

Step 2: Override the loadByQuery() function in \app\code\local\Econcess\EconSearch\Model\Resource\Query.php

class Econcess_EconSearch_Model_Resource_Query extends Mage_CatalogSearch_Model_Resource_Query
{
public function loadByQuery(Mage_Core_Model_Abstract $object, $value)
{
$select = $this->_getReadAdapter()->select()
->from($this->getMainTable())
->where('synonym_for=_utf8 ? COLLATE utf8_bin OR query_text=_utf8 ? COLLATE utf8_bin', $value)
->where('store_id=?', $object->getStoreId())
->order('synonym_for ASC')
->limit(1);
if ($data = $this->_getReadAdapter()->fetchRow($select)) {
$object->setData($data);
$this->_afterLoad($object);
}
return $this;
}
}

Step 3: Override the prepareResult() function in \app\code\local\Econcess\EconSearch\Model\Resource\Fulltext.php

class Econcess_EconSearch_Model_Resource_Fulltext extends Mage_CatalogSearch_Model_Resource_Fulltext
{
public function prepareResult($object, $queryText, $query)
{
$adapter = $this->_getWriteAdapter();
if (!$query->getIsProcessed()) {
$searchType = $object->getSearchType($query->getStoreId());
$preparedTerms = Mage::getResourceHelper('catalogsearch')
->prepareTerms($queryText, $query->getMaxQueryWords());
$bind = array();
$like = array();
$likeCond = '';
if ($searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_LIKE
|| $searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_COMBINE
) {
$helper = Mage::getResourceHelper('core');
$words = Mage::helper('core/string')->splitWords($queryText, true, $query->getMaxQueryWords());
foreach ($words as $word) {
$like[] = $helper->getCILike('s.data_index', $word, array('position' => 'any'));
}
if ($like) {
$likeCond = '(' . join(' AND ', $like) . ' COLLATE utf8_bin)';
$likeCond = str_replace('LIKE', 'LIKE _utf8', $likeCond);
}
}
$mainTableAlias = 's';
$fields = array(
'query_id' => new Zend_Db_Expr($query->getId()),
'product_id',
);
$select = $adapter->select()
->from(array($mainTableAlias => $this->getMainTable()), $fields)
->joinInner(array('e' => $this->getTable('catalog/product')),
'e.entity_id = s.product_id',
array())
->where($mainTableAlias.'.store_id = ?', (int)$query->getStoreId());
if ($searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_FULLTEXT
|| $searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_COMBINE) {
$bind[':query'] = implode(' ', $preparedTerms[0]);
$where = Mage::getResourceHelper('catalogsearch')
->chooseFulltext($this->getMainTable(), $mainTableAlias, $select);
}
if ($likeCond != '' && $searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_COMBINE) {
$where .= ($where ? ' OR ' : '') . $likeCond;
}
if ($likeCond != '' && $searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_LIKE) {
$select->columns(array('relevance' => new Zend_Db_Expr(0)));
$where = $likeCond;
}
if ($where != '') {
$select->where($where);
}
$sql = $adapter->insertFromSelect($select,
$this->getTable('catalogsearch/result'),
array(),
Varien_Db_Adapter_Interface::INSERT_ON_DUPLICATE);
$adapter->query($sql, $bind);
$query->setIsProcessed(1);
}
return $this;
}
}

Done!

... back to the blog