ph2m/magento2-elasticsearch

为 Magento 2 搜索使用 Elasticsearch

安装: 271

依赖: 0

建议者: 0

安全: 0

星标: 7

关注者: 4

分支: 1

开放问题: 0

类型:magento2-module

1.1.4 2024-09-04 16:11 UTC

This package is auto-updated.

Last update: 2024-09-04 16:12:04 UTC


README

安装

首先,安装 Magento 模块

composer require ph2m/magento2-elasticsearch

您需要安装 ElasticSearch 的 analysis-icu 插件。

您必须锁定 Elasticsearch 配置

php bin/magento config:set --lock catalog/search/elasticsearch7_server_hostname <elasticsearch_hostname>
php bin/magento config:set --lock catalog/search/elasticsearch7_server_port <elasticsearch_port>
php bin/magento config:set --lock catalog/search/elasticsearch7_index_prefix <elasticsearch_index_prefix>
php bin/magento config:set --lock catalog/search/elasticsearch7_enable_auth <elasticsearch_enable_auth>
php bin/magento config:set --lock catalog/search/elasticsearch7_username <elasticsearch_username>
php bin/magento config:set --lock catalog/search/elasticsearch7_password <elasticsearch_password>

将文件 es.php.sample 复制到您的 Magento pub 目录,并根据需要自定义它。

cp vendor/ph2m/magento2-elasticsearch/etc/es.php.sample pub/es.php

更新您的 Magento_Theme/templates/html/header.phtml 文件以包含搜索表单。

<?php echo $block->getChildHtml('ph2m.elasticsearch.search.form') ?>

您可以在您的主题中自定义模板文件 PH2M_Elasticsearch::search/form.phtml

安装后,重新索引。

php bin/magento indexer:reindex

添加新的搜索对象(品牌、博客文章等)

让我们假设您有一个模块 Vendor_Brand,并且您想将品牌添加到搜索中。

更新 di.xml 以添加字段映射器

<type name="Magento\Elasticsearch\Model\Adapter\FieldMapper\FieldMapperResolver">
    <arguments>
        <argument name="fieldMappers" xsi:type="array">
            <item name="brand" xsi:type="string">Vendor\Brand\Model\Adapter\FieldMapper\BrandFieldMapper</item>
        </argument>
    </arguments>
</type>

创建字段映射器类

<?php
declare(strict_types=1);

namespace Vendor\Brand\Model\Adapter\FieldMapper;

use Magento\Elasticsearch\Model\Adapter\FieldMapperInterface;

class BrandFieldMapper implements FieldMapperInterface
{
    public function getFieldName($attributeCode, $context = [])
    {
        return $attributeCode;
    }

    public function getAllAttributesTypes($context = [])
    {
        return [
            'name' => [
                'type' => 'text',
                'fields' => [
                    'keyword' => [
                        'type' => 'keyword',
                    ],
                ]
            ],
            'url_key' => [
                'type' => 'text',
            ],
        ];
    }
}

etc/indexer.xml 中声明新的索引器

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Indexer/etc/indexer.xsd">
    <indexer id="brandsearch_fulltext" view_id="brandsearch_fulltext" class="Vendor\Brand\Model\Indexer\Fulltext">
        <title translate="true">Brand Search</title>
        <description translate="true">Rebuild Brand fulltext search index</description>
    </indexer>
</config>

etc/mview.xml 中声明视图

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Mview/etc/mview.xsd">
    <view id="brandsearch_fulltext" class="Vendor\Brand\Model\Indexer\Fulltext" group="indexer">
        <subscriptions>
            <table name="brand" entity_column="brand_id"/>
        </subscriptions>
    </view>
</config>

创建索引器类 Vendor\Brand\Model\Indexer\Fulltext

<?php
declare(strict_types=1);

namespace Vendor\Brand\Model\Indexer;

use Magento\AdvancedSearch\Model\Client\ClientResolver;
use Magento\Elasticsearch\Model\Adapter\Elasticsearch;
use Magento\Elasticsearch\Model\Adapter\Index\IndexNameResolver;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Vendor\Brand\Api\Data\BrandInterface;
use Vendor\Brand\Query\Brand\GetListQuery;
use Psr\Log\LoggerInterface;

class Fulltext implements \Magento\Framework\Indexer\ActionInterface, \Magento\Framework\Mview\ActionInterface
{
    public function __construct(
        protected ClientResolver $clientResolver,
        protected GetListQuery $getListQuery,
        protected SearchCriteriaBuilder $searchCriteriaBuilder,
        protected Elasticsearch $elasticsearchAdapter,
        protected LoggerInterface $logger,
        protected IndexNameResolver $indexNameResolver
    ) {
    }

    public function execute($ids)
    {
        $this->executeList($ids);
    }

    public function executeFull(): void
    {
        $this->elasticsearchAdapter->cleanIndex(1, 'brand');
        $this->executeList([]);
        $this->elasticsearchAdapter->updateAlias(1, 'brand');
    }

    public function executeList(array $ids): void
    {
        $searchCriteria = $this->searchCriteriaBuilder;

        if (!empty($ids)) {
            $searchCriteria->addFilter(BrandInterface::BRAND_ID, $ids, 'in');
        }

        $brands = $this->getListQuery->execute($searchCriteria->create())->getItems();

        $brandsToReindex = [];
        foreach ($brands as $brand) {
            $brandsToReindex[] = [
                'name' => $brand->getName(),
                'url_key' => $brand->getUrlKey(),
            ];
        }

        try {
            $this->elasticsearchAdapter->addDocs($brandsToReindex, 1, 'brand');
        } catch (\Throwable $e) {
            $this->logger->error($e->getMessage());
        }
    }

    public function executeRow($id)
    {
        $this->executeList([$id]);
    }
}

etc/events.xml 中添加 save_after 观察者

<event name="brand_model_save_after">
    <observer name="brand_model_save_after" instance="Vendor\Brand\Observer\SaveAfter" />
</event>

以及相应的类

<?php declare(strict_types=1);

namespace Vendor\Brand\Observer;

use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Indexer\StateInterface;
use Magento\Indexer\Model\IndexerFactory;

class SaveAfter implements ObserverInterface
{
    public function __construct(
        protected IndexerFactory $indexerFactory,
        protected \Vendor\Brand\Model\Indexer\Fulltext $fulltextIndexer
    ) {
    }

    public function execute(Observer $observer): void
    {
        $index = $this->indexerFactory->create()->load('brandsearch_fulltext');

        if ($index->isScheduled()) {
            $index->invalidate();
        } else {
            $this->fulltextIndexer->executeRow($observer->getData('object')->getBrandId());

            $state = $index->getState();
            $state->setStatus(StateInterface::STATUS_VALID);
            $state->save();
            $index->setState($state);
        }
    }
}

同义词配置

您可以在“商店 > 配置 > 目录 > 目录 > 目录搜索 > 搜索同义词”中添加一些同义词。同义词必须由逗号分隔,每行一个同义词组。

Hyvä ready

此模块专为 Hyvä 设计。