Perform a catalog search in Magento. The default sorting will be by relevance. However, no actual sorting is applied to the result set. If you search by relevance descending or ascending the results will not change.
I tracked the problem down to the following file:
vendor\magentomodule-catalog-search\Model\ResourceModel\Fulltext\Collection.php
at Line 349 inside the function _renderFiltersBefore()
The problem is that _renderFiltersBefore is called before the call to setOrder(), and the check if ($this->order && 'relevance' === $this->order['field']) { will always have $this->order as null at this point.
This is most easily reproduced/examined by simply debugging a search request with breakpoints at both _renderFiltersBefore and setOrder inside the Collection.php file. You'll see that setOrder is called too late. For some reason the check if ($attribute != 'relevance') is performed in setOrder which prevents the order call from being added to the collection. It's almost as if it was intentionally ignoring relevance.
If I added the line $this->getSelect()->order('search_result.'. TemporaryStorage::FIELD_SCORE . ' ' . Select::SQL_DESC); to the _renderFiltersBefore function, the results or properly sorted by relevance. This was only done as a test to see if my suspicions were true, and not intended to be a solution.
Some more details.
I realize why setOrder() ignores relevance as the relevance "order by" clause is specially suited to the search query and can't be added as a regular order to the collection. It's still a problem that $this->order in the Collection class will always be null when checked.
I found that the first point where the query is actually executed due to the call to $block->getResultCount() in vendor\magentomodule-catalog-search\view\frontend\templates\result.phtml
My current solution is to extend/inject a subclass of "Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection" and override the method _renderFiltersBefore to have the following code:
protected function _renderFiltersBefore() {
    parent::_renderFiltersBefore();
    $order = $this->toolbar->getOrder();
    if(!$order || $order == 'relevance') {
        $this->getSelect()->order('search_result.'. TemporaryStorage::FIELD_SCORE . ' ' . Select::SQL_DESC);
    }
}
$this->toolbar is an instance of \Magento\Catalog\Model\Product\ProductListToolbar
Hi, thanks for reporting. I am just confirming this is still an issue in ver. 2.1.6
I am also experiencing this in 2.1.7
@AirmanAJK thank you for your feedback.
Please, format this issue according to the Issue reporting guidelines: with steps to reproduce, actual result and expected result.
Please, also identify which version of Magento you are running.
Hi @veloraven,
I am formatting this issue as per guidelines.
Title
The catalog search result is not being sorted by 'Relevance' by default.
Issue Description
Preconditions
Magento EE 2.1.6.
Need to have products with similar names, descriptions, short descriptions.
Steps to reproduce
Actual and Expected result
Expected Result
The default sort direction for search result list should be 'Relevance'.
Actual Result
The default sort direction for search result list is 'Product Name'.
Please add this to an internal ticket to be fixed.
Thanks
While this bug has now been finally added in TO-DO list for Magento Core team, I already found a feasible solution which doesn't require to override any core class as suggested in the first solution by @AirmanAJK.
In a custom module, I utilised plugin (which uses Interceptor Design Pattern) for _getCurrentOrder_ method in _Magento\CatalogBlock\Product\ProductListToolbar_.
For this example, I would use an arbitrary module named _Namesapce_Modulename_. So, once the module is created, in etc/frontend/di.xml use the following code:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Catalog\Block\Product\ProductList\Toolbar">
        <plugin name="namespace_modulename_catalog_product_list_toolbar_after_get_current_order"
                type="Namespace\Modulename\Plugin\Catalog\Block\Product\ProductList\Toolbar"
                sortOrder="1"
                disabled="false"
        />
    </type>
</config>
Now inside the plugin class
_Namespace/Modulename/Plugin / Catalog / Block / Product / ProductList / Toolbar.php_ use the following code:
<?php
namespace Namespace\Modulename\Plugin\Catalog\Block\Product\ProductList;
use Magento\Catalog\Model\Product\ProductList\Toolbar as ToolbarModel;
use Magento\Catalog\Model\Session as CatalogSession;
use Namespace\Modulename\Helper\Data as Helper;
class Toolbar extends \Magento\Framework\View\Element\Template
{
    protected $toolbarModel;
    protected $paramsMemorizeAllowed = true;
    protected $catalogSession;
    protected $helper;
    public function __construct(
        ToolbarModel $toolbar,
        CatalogSession $catalogSession,
        Helper $helper
    ) {
        $this->toolbarModel = $toolbar;
        $this->catalogSession = $catalogSession;
        $this->helper = $helper;
    }
    public function afterGetCurrentOrder(
        \Magento\Catalog\Block\Product\ProductList\Toolbar $subject
    ) {
        if (!$this->helper->getSearchSortOrderByRelevance()) {
            return;
        }
        $order = $subject->_getData('_current_grid_order');
        $orders = $subject->getAvailableOrders();
        $toolbarOrder = $this->toolbarModel->getOrder();
        if ($order && !isset($orders['relevance'])) {
            return $order;
        } else if ($order
            && isset($orders['relevance'])
            && $toolbarOrder == null
        ) {
            $keys = array_keys($orders);
            $defaultOrder = $keys[2];
        } else {
            $keys = array_keys($orders);
            $defaultOrder = $keys[0];
        }
        if (!$order || !isset($orders[$toolbarOrder])) {
            $order = $defaultOrder;
        }
        if ($order != $defaultOrder) {
            $this->memorizeParam('sort_order', $order);
        }
        $subject->setData('_current_grid_order', $order);
        return $order;
    }
    protected function memorizeParam($param, $value)
    {
        if ($this->paramsMemorizeAllowed && !$this->catalogSession->getParamsMemorizeDisabled()) {
            $this->catalogSession->setData($param, $value);
        }
        return $this;
    }
}
I also created a "Yes/No" admin configuration setting to make sure when Magento core team implement the fix this plugin can be disabled without touching any code. And using a helper return method _getSearchSortOrderByRelevance_, I am checking if we need to set the search result order to _relevance_.
Hope this helps someone.
Cheers!
Hi,
I see that the issue was fixed in the ticket MAGETWO-58964, but the fix wasn't backported into 2.1.x.
@AirmanAJK and @asrar7787, can you check if the fix working for you on 2.2?
ASAP fix if you need:
Create new module with plugin:
app/code/Vendor/Module/etc/config.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Vendor_Module" setup_version="1.0.0"/>
</config>
Create di file for out plugin:
app/code/Vendor/Module/etc/frontend/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection">
        <plugin name="product_sort_by_fix" type="Vendor\Module\Plugin\FullTextCollection"/>
    </type>
</config>
Create plugin file:
app/code/Vendor/Module/Plugin/FullTextCollection.php
<?php
namespace Vendor\Module\Plugin;
class FullTextCollection
{
    public function aroundSetOrder(\Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection $collection, $proceed, $attribute, $dir = 'ASC')
    {
        $collection->getSelect()->reset(\Zend_Db_Select::ORDER);
        $collection->addAttributeToSort($attribute, $dir);
        if ($attribute == 'relevance') {
            $collection->addAttributeToSort('entity_id', $dir);
        } else {
            $collection->addAttributeToSort('entity_id', 'ASC');
        }
        return $this;
    }
}
and final – registration file:
app/code/Vendor/Module/registration.php
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Vendor_Module',
    __DIR__
);
Run "php bin/magento setup:upgrade" command, and be happy :)
@zuzuman in the around method you're not calling the callable function $proceed in the around interceptor.
I think a slightly different version of your plugin would be using a before method instead.
...
use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection;
use Magento\Framework\DB\Select;
...
public function beforeSetOrder(Collection $collection, $attribute, $order = Select::SQL_DESC)
    {
        if ($attribute != 'relevance') {
            $order = Select::SQL_ASC; //This can be come from a settings if we don't want hard code it like this.
        }
        return [$attribute, $order];
    }`
Also if you consider that a specified sorting method, the plugin will override it anyway. Which means:
https://..../catalogsearch/result/index/?product_list_dir=desc&product_list_order=price
https://..../catalogsearch/result/index/?product_list_dir=asc&product_list_order=price
https://..../catalogsearch/result/index/?product_list_order=price
They will give you the same result. To fix this problem your plugin can me modified as the follow:
...
use Magento\Catalog\Model\Product\ProductList\Toolbar as ToolbarModel;
use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection;
use Magento\Framework\DB\Select;
...
    public function __construct(ToolbarModel $toolbarModel)
    {
        $this->toolbarModel = $toolbarModel;
    }
    public function beforeSetOrder(Collection $collection, $attribute, $order = Select::SQL_DESC)
    {
        if ($attribute != 'relevance' && !$this->toolbarModel->getDirection()) {
            $order = Select::SQL_ASC;
        }
        return [$attribute, $order];
    }
}
                    Hello. I have a Magento 2.1.15 CE implementation that is suffering from this bug. The search option doesn't work as expected.
Is there any patch for that ? I know that I could upgrade my Magento, but unfortunately this is not an option. 
I tried the solution provided by @asrar7787 but unfortunately I could not find the missing code ( Helper class).
Any help would be appreciated. Thank you.
@kpaul1978
The helper class is just returning admin configuration (yes/no) value. You don’t have to have it if you just want to try. As said, this admin configuration I created for making this solution compatible with any future fixes from Magento core.
Hope this helps!
Many thanks for your help and your quick answer.
I know that your time is valuable, but I really appreciate any answer.
I removed all references to the helper class / object.
I run  php bin/magento setup:di:compile , did another search but without
any improvement.
I attached the module that I put together.
Thank you,
Paul
On Wed, Aug 7, 2019 at 10:14 AM Asrar Alam notifications@github.com wrote:
@kpaul1978 https://github.com/kpaul1978
The helper class is just returning admin configuration (yes/no) value. You
don’t have to have it if you just want to try. As said, this admin
configuration I created for making this solution compatible with any future
fixes from Magento core.Hope this helps!
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/magento/magento2/issues/9066?email_source=notifications&email_token=ACQKDY4CSMYZLPV5LCU3AJLQDJY5BA5CNFSM4DF3JNN2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD3XOBZA#issuecomment-518971620,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ACQKDY235W6KWJSMGMNVEZ3QDJY5BANCNFSM4DF3JNNQ
.
The Issue should be re-verified on the latest Magento code and re-Confirmed if its still actual