Magento2添加SOLR和ELASTICSEARCH搜索引擎
Magento 2社区版仅支持MySQL搜索引擎,但有些项目需要更好的搜索引擎才能提高销售额或转换率。 在这种情况下,我们可以选择实施Solr或Elasticsearch搜索引擎。magento2商业自带支持Solr,请查看magento2社区办和magento2企业版的比较
在这篇文章中,我们将创建一个框架代码和简单的示例,它将介绍实现其他搜索引擎(如Solr或Elasticsearch)的主要类和方法。如果你进入到Magento 2 后台管理,您可以在这个位置找到搜索引擎配置:Stores -> Configuration -> Catalog -> Catalog Search 然后下拉 “Search Engine”选项。
在下拉列表中,您将注意到您只有MySQL引擎,我们的第一步是在此下拉列表中添加标签为“Solr”的额外选项。那么,现在开始吧。
在你的模块etc文件夹中,您需要使用以下xml代码创建文件di.xml:
<type name="Magento\Search\Model\Adminhtml\System\Config\Source\Engine"> <arguments> <argument name="engines" xsi:type="array"> <item name="solr" xsi:type="string">Solr</item> </argument> </arguments> </type>
使用此xml代码,现在我们已经在下拉列表中添加了一个新选项,其选项名称为“Solr”。如果您正确创建并清理了Magento缓存,您将能够在下拉列表中看到它,其中会有一个新选项“Solr”。如果您看到它,则表示您已正确添加它。
在下一步中,我们将从php类开始,这些类负责将数据索引到搜索服务器。
首先,我们要implement Engine类,在di.xml中放入以下代码:
<type name="Magento\CatalogSearch\Model\ResourceModel\EngineProvider"> <arguments> <argument name="engines" xsi:type="array"> <item name="solr" xsi:type="string">Search\Solr\Model\ResourceModel\Engine</item> </argument> </arguments> </type>
您可以看到我们为“Seach\Solr\Model\ResourceModel\Engine” 引入了我们自己的Engine类。引擎类负责在数据进入我们的indexerHandler类(solr服务器之前的最后一个端点)之前准备数据,而Engine类必须实现接口:\Magento\CatalogSearch\Model\ResourceModel\EngineInterface。
接口类包含以下四种方法: - processAttributeValue 准备要存储在solr索引中的属性值 - getAllowedVisibility 检索当前引擎允许的可见性值 - allowAdvancedIndex 定义当前搜索引擎是否支持高级索引 - prepareEntityIndex 将索引数组作为分隔符粘贴的字符串
这些方法是必需的,必须在Engine类中实现。为了更好地理解,您可以在类似的MySQL类中检查/比较逻辑:Magento\CatalogSearch\Model\ResourceModel\Engine
我们的框架类示例如下:
<?php namespace Search\Solr\Model\ResourceModel; use Magento\CatalogSearch\Model\ResourceModel\EngineInterface; class Engine implements EngineInterface { protected $catalogProductVisibility; private $indexScopeResolver; public function __construct( \Magento\Catalog\Model\Product\Visibility $catalogProductVisibility, \Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver $indexScopeResolver ) { $this->catalogProductVisibility = $catalogProductVisibility; $this->indexScopeResolver = $indexScopeResolver; } public function getAllowedVisibility() { return $this->catalogProductVisibility->getVisibleInSiteIds(); } public function allowAdvancedIndex() { return false; } public function processAttributeValue($attribute, $value) { return $value; } public function prepareEntityIndex($index, $separator = ' ') { return $index; } public function isAvailable() { return true; } } ?>
下一步是创建名为“Seach\Solr\Model\Indexer\IndexerHandler”的indexerHandler,它将实现Magento\Framework\Indexer\SaveHandler\IndexerInterface。 要实现IndexerHandler,您需要在di.xml文件中添加以下代码:
<type name="Magento\CatalogSearch\Model\Indexer\IndexerHandlerFactory"> <arguments> <argument name="handlers" xsi:type="array"> <item name="solr" xsi:type="string">Search\Solr\Model\Indexer\IndexerHandler</item> </argument> </arguments> </type>
如果打开IndexerInterface,您将看到四个必须实现的方法: - saveIndex 将实体数据添加到索引 - deleteIndex 从索引中删除实体数据 - cleanIndex 从索引中删除所有数据 - isAvailable 定义引擎是否可用(您可以ping到solr服务器和检查它是否连接)。
我们的IndexerHandler框架类示例如下:
<?php namespace Search\Solr\Model\Indexer; use Magento\Eav\Model\Config; use Magento\Framework\App\ResourceConnection; use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Framework\Indexer\SaveHandler\IndexerInterface; use Magento\Framework\Indexer\IndexStructureInterface; use Magento\Framework\Search\Request\Dimension; use Magento\Framework\Search\Request\IndexScopeResolverInterface; use Magento\Framework\Indexer\SaveHandler\Batch; use Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver; class IndexerHandler implements IndexerInterface { private $indexStructure; private $data; private $fields; private $resource; private $batch; private $eavConfig; private $batchSize; private $indexScopeResolver; public function __construct( Batch $batch, array $data, $batchSize = 50 ) { $this->batch = $batch; $this->data = $data; $this->batchSize = $batchSize; } public function saveIndex($dimensions, \Traversable $documents) { foreach ($this->batch->getItems($documents, $this->batchSize) as $batchDocuments) { } } public function deleteIndex($dimensions, \Traversable $documents) { foreach ($this->batch->getItems($documents, $this->batchSize) as $batchDocuments) { } } public function cleanIndex($dimensions) { } public function isAvailable() { return true; } }
在这些方法中,您应该实现Solr PHP客户端,它将对SOLR服务器进行列表操作。经常用到的是Solarium PHP客户端。
通过此步骤,我们将结束向搜索服务器索引数据的过程。
现在您可以检查您的索引器是否可以使用以下命令(在magento2 后台将搜索引擎设置为SOLR之前):
php /bin/magento indexer:reindex catalogsearch_fulltext
在接下来的最后一步中,我们将了解如何在Magento 2前端实现新的搜索引擎。所以,我们必须修改di.xml并添加以下代码:
<type name="Magento\Search\Model\AdapterFactory"> <arguments> <argument name="adapters" xsi:type="array"> <item name="solr" xsi:type="string">Search\Solr\SearchAdapter\Adapter</item> </argument> </arguments> </type>
我们的新适配器类是Seach\Solr\SearchAdapter\Adapter。适配器类需要实现Magento\Framework\Search\AdapterInterface。在我们的适配器中,我们必须实现方法query - 此方法接受查询请求并处理它。看看我们的例子,一切都会更清晰。
<?php namespace Search\Solr\SearchAdapter; use Magento\Framework\Search\AdapterInterface; use Magento\Framework\Search\RequestInterface; use Magento\Framework\Search\Response\QueryResponse; use Search\Solr\SearchAdapter\Aggregation\Builder; class Adapter implements AdapterInterface { protected $responseFactory; protected $connectionManager; protected $aggregationBuilder; public function __construct( ResponseFactory $responseFactory, Builder $aggregationBuilder, ConnectionManager $connectionManager ) { $this->responseFactory = $responseFactory; $this->aggregationBuilder = $aggregationBuilder; $this->connectionManager = $connectionManager; } /** * @param RequestInterface $request * @return QueryResponse */ public function query(RequestInterface $request) { $client = $this->getConnection(); $documents = []; $documents[1007] = array('entity_id'=>'1007', 'score'=>46.055); $documents[1031] = array('entity_id'=>'1031', 'score'=>45.055); $documents[1120] = array('entity_id'=>'1120', 'score'=>44.055); $aggregations = $this->aggregationBuilder->build($request, $documents); $response = [ 'documents' => $documents, 'aggregations' => $aggregations, ]; return $this->responseFactory->create($response); } public function getConnection(){ return $this->connectionManager->getConnection(); } } ?>
在我们的示例适配器类中,我我们有一串产品entity_ids:1007,1031,1120来自于我们的数据库产品id,仅用于测试目的。如果你想深入挖掘,我建议你检查MySQL适配器的工作原理。
通过这一步,我们结束了我们的示例。即使事情看起来很复杂,但当你开始工作时,一切都会好起来的。我希望您能喜欢Magneto 2新搜索引擎的编码。