3

Ok here is the scenario, I've tested that on a fresh Magento 1.9.2.4 with sample data.

Let's say I have a search term that is "tee".

1st Test

  • remove all synonyms for "tee"
  • delete "tee" from the search terms
  • search for "tee" in the frontend
  • "tee" is added back to the search terms
  • add synonyms for "tee" (example: if I edit "t-shirt" search term and I add "tee" in the "Synonym For" entry)
  • search for "tee" in the frontend
  • "tee" number of uses is increased by 1

2nd Test

  • remove all synonyms for "tee"
  • delete "tee" from the search terms
  • search for "tee" in the frontend
  • "tee" is added back to the search terms
  • add synonyms for "tee" (example: if I edit "t-shirt" search term and I add "tee" in the "Synonym For" entry)
  • EXTRA STEP HERE: delete "tee" from the search terms
  • search for "tee" in the frontend
  • "tee" is not being added back to the search terms

Results

To me, that behavior is totally inconsistent, it should:

  • either not increase the number of uses of "tee" in the first step
  • or add back "tee" to the search terms with number of uses = 1 in the second step

Thus, the search reports are not accurate as if someone search "tee" as it is never added back to the search terms it will not be taken into consideration in the report.

To me it sounds like a bug but I may be missing something.

Does that behavior sound logic to you and if so could you explain me why ?

3

TL;DR

Debugging the issue

Here's the workflow:

Under app/code/core/CatalogSearch/controllers/ResultController.php in the indexAction(), the search term is retrieved by the following code:

$query = Mage::helper('catalogsearch')->getQuery();

That corresponds to the following:

public function getQuery()
{
    if (!$this->_query) {
        $this->_query = Mage::getModel('catalogsearch/query')
            ->loadByQuery($this->getQueryText());
        if (!$this->_query->getId()) {
            $this->_query->setQueryText($this->getQueryText());
        }
    }
    return $this->_query;
}

When you check the resource model loadByQuery method, here's what happens:

public function loadByQuery(Mage_Core_Model_Abstract $object, $value)
{
    $readAdapter = $this->_getReadAdapter();
    $select = $readAdapter->select();

    $synonymSelect = clone $select;
    $synonymSelect
        ->from($this->getMainTable())
        ->where('store_id = ?', $object->getStoreId());

    $querySelect = clone $synonymSelect;
    $querySelect->where('query_text = ?', $value);

    $synonymSelect->where('synonym_for = ?', $value);

    $select->union(array($querySelect, "($synonymSelect)"), Zend_Db_Select::SQL_UNION_ALL)
        ->order('synonym_for ASC')
        ->limit(1);

    $data = $readAdapter->fetchRow($select);
    if ($data) {
        $object->setData($data);
        $this->_afterLoad($object);
    }

    return $this;
}

As you can see, the code here looks for both query_text and synonym_for results using an UNION statement.

The result query would look like this:

SELECT `catalogsearch_query`.* 
FROM `catalogsearch_query` 
WHERE (store_id = '1') AND (query_text = 'tee') 
UNION ALL (
    SELECT `catalogsearch_query`.* 
    FROM `catalogsearch_query` 
    WHERE (store_id = '1') AND (synonym_for = 'tee')
) 
ORDER BY `synonym_for` ASC 
LIMIT 1

Thus:

  • in the 1st test, the original term "tee" is retrieved and thus, its number of uses is increased by 1 but not the number of uses for the synonyms
  • in the 2nd test, the synonym term "t shirt" is retrieved and its number of uses is increased but the original term is not recreated

Then further in the indexAction method we've got the following that takes care of the number of uses increments:

if ($query->getId()) {
     $query->setPopularity($query->getPopularity()+1);
}
else {
    $query->setPopularity(1);
}

Fixing the issue

To me there's two possible fixes:

  • the first one would be to use an observer when a search term is deleted so every synonyms for this term are removed.
  • the second one would require a lot more work and would be to modify the current system totally so it handles the creation of a missing search term when a synonym exists.

Side note

I had a look at Magento 2 to see how it handles it.

Funny thing is, Magento 2 does not use loadByQuery to get the search term but loadByQueryText which looks like this and basically skip the synonym:

public function loadByQueryText(AbstractModel $object, $value)
{
    $select = $this->getConnection()->select()->from(
        $this->getMainTable()
    )->where(
        'query_text = ?',
        $value
    )->where(
        'store_id = ?',
        $object->getStoreId()
    )->limit(
        1
    );
    $data = $this->getConnection()->fetchRow($select);
    if ($data) {
        $object->setData($data);
        $this->_afterLoad($object);
    }
    return $this;
}

In Magento 1, this method also exists but it is only used in the backend when a search term is saved.

I assume that synonyms are handled differently in Magento 2 but I have not tested the problem I posted on M2 yet.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.