Not the actual answer but you can identify some ways.
Add two plugins one is for GetLoadedProductCollection and second is for what ElasticSearch returning ids.
File: di.xml
<type name="Magento\Catalog\Block\Product\ListProduct">
<plugin name="VendorModule::logListProductQuery" type="Vendor\Module\Plugin\Catalog\Product\PluginListProduct"/>
</type>
File : PluginListProduct.php
namespace Vendor\Module\Plugin\Catalog\Product;
use Psr\Log\LoggerInterface;
class PluginListProduct
{
public function __construct(
LoggerInterface $logger
)
{
$this->logger = $logger;
}
public function afterGetLoadedProductCollection(MageListProduct $subject, $result)
{
$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/PluginListProductQuery.log');
$logger = new \Zend\Log\Logger();
$logger->addWriter($writer);
$logger->info($result->getSelect()->__toString());
return $result;
}
}
Also, add a custom plugin it will help you to identify which ids ElasticSearch returning.
This will only useful if ElasticSearch is using as Catalog Search engine.
File: di.xml
<type name="Magento\Elasticsearch\SearchAdapter\ResponseFactory">
<plugin name="Vendor_Module::responseCheckFromElasticSearch"
type="Vendor\Module\Plugin\ResponseCheck"
disabled="false"/>
</type>
File: ResponseCheck.php
<?php
namespace Vendor\Module\Plugin;
use Psr\Log\LoggerInterface;
class ResponseCheck
{
protected $logger;
public function __construct(
LoggerInterface $logger
)
{
$this->logger = $logger;
}
public function beforeCreate(\Magento\Elasticsearch\SearchAdapter\ResponseFactory $subject, $result)
{
$docRaw = $docRawScore = array();
$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/ElasticResponseCheck.log');
$logger = new \Zend\Log\Logger();
$logger->addWriter($writer);
if (!is_array($result) || empty($result)) return false;
foreach ($result['documents'] as $rawDocument) {
$docRaw[] = $rawDocument['_id'];
$docRawScore[] = $rawDocument['_score'];
}
$logger->info('ID: ' . implode(',', $docRaw));
$logger->info('SCORE: ' . implode(',', $docRawScore));
$logger->info('*************************************** END *********************************************');
}
}
Probably you will get following order by in PluginListProductQuery.log and compare these ids with what is returning in ElasticResponseCheck.log
With ElasticSearch as a search engine
possible order by for Elastic search would be - ORDER BY FIELD(e.entity_id,103,102,101)
With MySQL as a search engine
possible order by - ORDER BY cat_index.position asc, e.entity_id DESC LIMIT 4
Hope this helps.