在这篇博客中,我们将重点关注搜索结果页面。确保您至少拥有Klevu Premium定价计划,以便能够选择模板。

如果你转到

System > Configuration > Klevu > Search configuration > Search Result Page Settings 

你会看到这个下拉列表:

它的目的是选择保留您的主题布局选项,但它清楚地表明建议使用基于Klevu模板。为什么会这样?我们将看到搜索如何与两个模板一起使用以及所选模板中包含哪些妥协。

 

Klevu模板

基于KLUV模板的搜索结果页面真的很有魅力,快速的ajax结果和属性多选择让你想知道为什么你甚至想处理Magento搜索。我们将浏览器设置为开发者模式,看看发生了什么。网址仍然存在http://magento.loc/search/result/?q=tees,但是对于所选的每个新功能(排序,价格范围,页面等),都会向托管我们搜索的Klevu云主机发出XHR请求,

http://eucs6.ksearchnet.com/cloud-search/n-search/search

参数

ticket=klevu-54597553548116773
term=tees                        // searched term
sortPrice=false
ipAddress=undefined
analyticsApiKey=klevu-54597553548116773
klevuShowOutOfStockProducts=true
klevuFetchPopularTerms=false
klevu_priceInterval=500
fetchMinMaxPrice=true
klevu_multiSelectFilters=true
noOfResults=9                   // items per page, defaults are 9, 15 and 30
paginationStartsFrom=18         // get us items for page 3 since 0-8 are showed on page 1, 9-17 on page 2 
klevuSort=lth                   // sort by price: low to high
enableFilters=true
filterResults=category%3Atees%3B%3Bklevu_price%3A22%20-%2044  // selected category "tees", price range 22-44
category=KLEVU_PRODUCT
sv=2129
lsqt=WILDCARD_AND
responseType=json

Klevu Developer API文档中对此进行了解释,这里可以看到整体响应在这种情况下,Magento就像Klevu餐厅的客人一样 - Magento订购具有指定标准的商品,Klevu专门提供所要求的商品。从响应中可以看出,如果有24个查询结果,并且我们在最后一页上每页指定9个项目,Klevu将仅返回最后6个项目(前18个在第1页和第2页)。

 

Magento模板

 

 

是的,我们可以设计Klevu模板,以适应其余的商店,但它不会完全适合。例如,通过第三方的分层导航扩展和附加到产品的自定义附加数据(如可用大小),Category页面将具有特定的功能。将它们“复制并粘贴”到搜索结果页面的最佳方法是使用现有的Magento模板。现在看这里,但在这种情况下,Klevu餐厅更像是自助服务。当您搜索“T恤”时,一切看起来都像是常规的Magento目录搜索。即使是URL也是如此http://magento.loc/catalogsearch/result/?q=tees。Klevu用其更干净的类Cleaner干扰搜索流,该类重写默认的Magento\Framework\Search\Request\Cleaner类。

public function klevuQueryCleanup($requestData){
 
        // check if we are in search page
        if(!isset($requestData['queries']['quick_search_container'])) return $requestData;
        //check if klevu is supposed to be on
        if ($this->klevuConfig->isLandingEnabled()!=1 || !$this->klevuConfig->isExtensionConfigured()) return $requestData;
        //save data in session so we do not request via api for filters
        $queryTerm = $requestData['queries']['search']['value'];
        $queryScope = $requestData['dimensions']['scope']['value'];
        $idList = $this->sessionManager->getData('ids_'.$queryScope.'_'.$queryTerm);
        if(!$idList){
            $idList = $this->klevuRequest->_getKlevuProductIds($queryTerm);
            if(empty($idList)) $idList = array(0);
            $this->sessionManager->setData('ids_'.$queryScope.'_'.$queryTerm,$idList );
        }
        //register the id list so it will be used when ordering
        $this->magentoRegistry->unregister('search_ids');
        $this->magentoRegistry->register('search_ids', $idList);  //pulled out in ScoreBuilder class!
 
        // .... //
        return $requestData;
}

所有搜索的术语都会与相应的结果ID一起保存在当前会话中。如果可以在会话中找到查询,则结果ID将被拉出以供另一次使用以将请求保存到Klevu云主机。否则,将使用端点向云主机发出请求

http://eucs6.ksearchnet.com/cloud-search/n-search/idsearch
 
//notice that is different from URL used for search with Klevu template!

参数

ticket = klevu-54597553548116773
noOfResults = 2000
term = tees
paginationStartsFrom = 0
enableFilters = false
klevuShowOutOfStockProducts = true
category => KLEVU_PRODUCT

响应将如下所示:

{
   "meta":{
      "totalResultsFound":"27",
      "typeOfQuery":"WILDCARD_AND",
      "paginationStartFrom":"0",
      "noOfResults":"2000"
   },
   "result":[
      {
         "id":"1529-1517",
         "itemGroupId":"1529"
      },
      {
         "id":"1449-1441",
         "itemGroupId":"1449"
      },
       ....
       ,
      {
         "id":"1831-1826",
         "itemGroupId":"1831"
      }
   ]
}

结果项看起来不像Magento产品ID,但由于该_getKlevuProductIds功能,变量$idList包含真实的ID。请注意,与使用Klevu模板时给出的响应相比,此响应中的信息量要小得多。其原因是,在从Klevu\Search\Adapter\Mysql\ScoreBuilder类中的Magento Registry获取给定id列表并将其放入MySQL FIELD函数之后,Magento的工作方式类似于执行默认Catalog Search–创建临时表,在查询中插入这个“FIELD(...)”部分等等只需要它就可以了。

// Klevu\Search\Adapter\Mysql\ScoreBuilder
 
  public function build()
    {
        $scoreAlias = parent::getScoreAlias();
        $sessionOrder = $this->magentoRegistry->registry('search_ids');
        if(is_array($sessionOrder)) return "FIELD(search_index.entity_id,".implode(",",array_reverse($sessionOrder)).") AS {$scoreAlias}";
        return parent::build();
    }

因此,基本上,Klevu提供了适合搜索查询的id列表,并让Magento在排序、优先级、分页和其他方面处理它们。继续与Klevu 餐厅-现在很清楚自助服务的比较是从哪里来的。这就像Klevu的服务员接受了我们的订单(实际上,由于搜索结果页面上缺少过滤器,这不会很复杂),并给我们带来了自己做定餐的原料。但是我们有搜索结果页面,正如我们所希望的!

 

可能的问题

对于拥有大量产品的商店,Klevu云主机在搜索某些通用术语时可以返回超过1000个条目。请求中没有“页面”参数可以规定我们在哪个页面以及每页显示的项目数量。如果你搜索“发球台”,你的商店Klevu有1000个发球台,你可以得到所有这些!您已选择在搜索结果页面上显示9,15,30或X号码。而不是1000个发球台,你最终可能会遇到这个意外

Exception #0 (Zend_Db_Statement_Exception): SQLSTATE[42S22]: Column not found: 1054 Unknown column 'FIELD(search_index.entity_id,163182,163119,140982,141045,140919,140667,140730,140856,140415,140352,140541,140289,140478,135573,135384,129087,129045,129465,70080,70017,69765,69954,69639,69702,5' in 'field list'

修复 - 重写Klevu\Search\Adapter\Mysql\ScoreBuilder类:

namespace Magease\Fixes\Model\Klevu\Search\Adapter\Mysql;
 
use Magento\Framework\Registry as MagentoRegistry;
 
class ScoreBuilder extends \Klevu\Search\Adapter\Mysql\ScoreBuilder   
{
    private $magentoRegistry;
 
    public function __construct(
        MagentoRegistry $magentoRegistry
    ) {
        $this->magentoRegistry = $magentoRegistry;
        parent::__construct($magentoRegistry);
    }
 
    public function build()
    {
        $scoreAlias = parent::getScoreAlias();
        $sessionOrder = $this->magentoRegistry->registry('search_ids');
        if(is_array($sessionOrder)) {
            foreach ($sessionOrder as $search_id) {
                if (!is_numeric($search_id)) {
                    return false;
                }
            }
            return new \Zend_Db_Expr("FIELD(search_index.entity_id,".implode(",",array_reverse($sessionOrder)).") AS {$scoreAlias}");
        }
        return parent::build();
    }
}

原始构建方法返回包含适合搜索标准的产品ID的字符串。太长太长的ID列表创建字符串,然后产生preg_jit_stacklimit_error与模式regex_column_expr preg_match,在zend_db_select -> _tablecols。在这种情况下,MySQL FIELD函数被错误地解释为列,而不是导致MySQL未知列异常的函数。正确输出preg_match将导致创建Zend_Db_Expr,因此这里将返回它,而不是返回字符串,以绕过有问题的preg_.。以防万一,我们增加了检查,如果$SESSION ORD只包含数字