Skip to content

Commit

Permalink
Algolia Elastic Search Adapters for ES6/5 (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
bsuravech authored Oct 8, 2019
1 parent f8d24c2 commit b5f28dc
Show file tree
Hide file tree
Showing 8 changed files with 302 additions and 7 deletions.
113 changes: 113 additions & 0 deletions Adapter/AlgoliaElasticSearch5Adapter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php

namespace Algolia\AlgoliaSearchElastic\Adapter;

use Algolia\AlgoliaSearch\Helper\AdapterHelper;
use Magento\Elasticsearch\Elasticsearch5\SearchAdapter\Adapter as ElasticSearch5Adapter;
use Magento\Elasticsearch\Elasticsearch5\SearchAdapter\Mapper;
use Magento\Elasticsearch\SearchAdapter\Aggregation\Builder as AggregationBuilder;
use Magento\Elasticsearch\SearchAdapter\ConnectionManager;
use Magento\Elasticsearch\SearchAdapter\ResponseFactory;
use Magento\Elasticsearch\SearchAdapter\QueryContainerFactory;
use Magento\Framework\Search\RequestInterface;
use Psr\Log\LoggerInterface;

class AlgoliaElasticSearch5Adapter extends ElasticSearch5Adapter
{

/** @var AdapterHelper */
private $adapterHelper;

/** @var QueryContainerFactory */
private $queryContainerFactory;

/**
* AlgoliaElasticSearch5Adapter constructor.
* @param ConnectionManager $connectionManager
* @param Mapper $mapper
* @param ResponseFactory $responseFactory
* @param AggregationBuilder $aggregationBuilder
* @param QueryContainerFactory $queryContainerFactory
* @param LoggerInterface|null $logger
* @param AdapterHelper $adapterHelper
*/
public function __construct(
ConnectionManager $connectionManager,
Mapper $mapper,
ResponseFactory $responseFactory,
AggregationBuilder $aggregationBuilder,
QueryContainerFactory $queryContainerFactory,
LoggerInterface $logger = null,
AdapterHelper $adapterHelper
) {

parent::__construct($connectionManager, $mapper, $responseFactory, $aggregationBuilder, $queryContainerFactory,
$logger);

$this->adapterHelper = $adapterHelper;
$this->queryContainerFactory = $queryContainerFactory;

}

/**
* @param RequestInterface $request
* @return \Magento\Framework\Search\Response\QueryResponse
*/
public function query(RequestInterface $request)
{
if (!$this->adapterHelper->isAllowed()
|| !(
$this->adapterHelper->isSearch() ||
$this->adapterHelper->isReplaceCategory() ||
$this->adapterHelper->isReplaceAdvancedSearch() ||
$this->adapterHelper->isLandingPage()
)
) {
return parent::query($request);
}

$aggregationBuilder = $this->aggregationBuilder;
$query = $this->mapper->buildQuery($request);
$aggregationBuilder->setQuery($this->queryContainerFactory->create(['query' => $query]));

$rawResponse = [];
$totalHits = 0;
$table = null;

try {
// If instant search is on, do not make a search query unless SEO request is set to 'Yes'
if (!$this->adapterHelper->isInstantEnabled() || $this->adapterHelper->makeSeoRequest()) {
list($rawResponse, $totalHits) = $this->adapterHelper->getDocumentsFromAlgolia($request);
$rawResponse = $this->transformResponseForElastic($rawResponse);
}

} catch (AlgoliaConnectionException $e) {
return parent::query($request);
}

$aggregations = $aggregationBuilder->build($request, $rawResponse);
$response = [
'documents' => $rawResponse,
'aggregations' => $aggregations,
'total' => $totalHits,
];

return $this->responseFactory->create($response);
}

/**
* @param array $rawResponse
* @return array
*/
private function transformResponseForElastic(array $rawResponse)
{
if (count($rawResponse) > 0) {
foreach ($rawResponse as &$hit) {
$hit['_id'] = $hit['entity_id'];
}
$rawResponse['hits'] = ['hits' => $rawResponse];
}

return $rawResponse;
}
}
107 changes: 107 additions & 0 deletions Adapter/AlgoliaElasticSearchAdapter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

namespace Algolia\AlgoliaSearchElastic\Adapter;

use Algolia\AlgoliaSearch\Helper\AdapterHelper;
use Magento\Elasticsearch\SearchAdapter\Adapter as ElasticSearchAdapter;
use Magento\Elasticsearch\SearchAdapter\Aggregation\Builder as AggregationBuilder;
use Magento\Elasticsearch\SearchAdapter\ConnectionManager;
use Magento\Elasticsearch\SearchAdapter\Mapper;
use Magento\Elasticsearch\SearchAdapter\ResponseFactory;
use Magento\Elasticsearch\SearchAdapter\QueryContainerFactory;
use Magento\Framework\Search\RequestInterface;

class AlgoliaElasticSearchAdapter extends ElasticSearchAdapter
{

/** @var AdapterHelper */
private $adapterHelper;

/** @var QueryContainerFactory */
private $queryContainerFactory;

/**
* AlgoliaElasticSearch5Adapter constructor.
* @param ConnectionManager $connectionManager
* @param Mapper $mapper
* @param ResponseFactory $responseFactory
* @param AggregationBuilder $aggregationBuilder
* @param QueryContainerFactory $queryContainerFactory
* @param AdapterHelper $adapterHelper
*/
public function __construct(
ConnectionManager $connectionManager,
Mapper $mapper,
ResponseFactory $responseFactory,
AggregationBuilder $aggregationBuilder,
QueryContainerFactory $queryContainerFactory,
AdapterHelper $adapterHelper
) {

parent::__construct($connectionManager, $mapper, $responseFactory, $aggregationBuilder, $queryContainerFactory);

$this->adapterHelper = $adapterHelper;
}

/**
* @param RequestInterface $request
* @return \Magento\Framework\Search\Response\QueryResponse
*/
public function query(RequestInterface $request)
{
if (!$this->adapterHelper->isAllowed()
|| !(
$this->adapterHelper->isSearch() ||
$this->adapterHelper->isReplaceCategory() ||
$this->adapterHelper->isReplaceAdvancedSearch() ||
$this->adapterHelper->isLandingPage()
)
) {
return parent::query($request);
}

$aggregationBuilder = $this->aggregationBuilder;
$query = $this->mapper->buildQuery($request);
$aggregationBuilder->setQuery($this->queryContainerFactory->create(['query' => $query]));

$rawResponse = [];
$totalHits = 0;
$table = null;

try {
// If instant search is on, do not make a search query unless SEO request is set to 'Yes'
if (!$this->adapterHelper->isInstantEnabled() || $this->adapterHelper->makeSeoRequest()) {
list($rawResponse, $totalHits) = $this->adapterHelper->getDocumentsFromAlgolia($request);
$rawResponse = $this->transformResponseForElastic($rawResponse);
}

} catch (AlgoliaConnectionException $e) {
return parent::query($request);
}

$aggregations = $aggregationBuilder->build($request, $rawResponse);
$response = [
'documents' => $rawResponse,
'aggregations' => $aggregations,
'total' => $totalHits,
];

return $this->responseFactory->create($response);
}

/**
* @param array $rawResponse
* @return array
*/
private function transformResponseForElastic(array $rawResponse)
{
if (count($rawResponse) > 0) {
foreach ($rawResponse as &$hit) {
$hit['_id'] = $hit['entity_id'];
}
$rawResponse['hits'] = ['hits' => $rawResponse];
}

return $rawResponse;
}
}
11 changes: 6 additions & 5 deletions LICENSE → LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
MIT License
The MIT License (MIT)

Copyright (c) 2019 Algolia
http://www.algolia.com/

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -9,13 +10,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
37 changes: 35 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,35 @@
# algoliasearch-magento-2-es-compatibility
Algolia Search ES Compatibility module for Magento >=2.3.1 || >=2.2.8 and Algolia Search >=1.12 extension
# Algolia Search for Elastic Search Compatibility

Algolia Search Elastic Search Compatibility module for Magento 2 >=2.3.1 || >=2.2.8

As Magento has begun to fully support Elastic Search as the default Search Engine, this module was created to make the Algolia Magento 2 extension compatible with this search engine. We choose to make this a separate extension as not all versions of Magento will include Elastic Search by default. Please see the chart below for compatibility:

| Magento Version | Elastic Search | Is default? |
| :----: | :----: | :----: |
| \>= 2.3.1 | 6.x | Yes
| < 2.3.1 | 5.2 | No
| \>= Commerce 2.2.8 | 6.x | Yes |
| < Commerce 2.2.3 | 5.1 | No |

You can read more on Elastic Search by reading the magento devdocs here: https://devdocs.magento.com/guides/v2.3/config-guide/elasticsearch/es-overview.html


**Please be advised.** If you are on a version that does not have Elastic Search enabled by default, it is not necessary to switch your Search Engine to Elastic Search and install this compatibility.

Additionally, if you are using the configuration settings "Stores > Configuration > Algolia Search > Advance > Make a backend search query" set to "No", it is not required to utilize this module.

---

### Features dependent on this compatibility
#### Backend Search
Algolia will replace the results returned by the search adapter for Elastic Search.

You can test for backend search by changing your configuration for "Stores > Configuration > Algolia Search > Advance > Make a backend search query" to "Yes".

Results can be reviewed by going to view source and seeing if the HTML rendered results reflect Algolia Search returned results.


#### Backend Facet Rendering
If instantsearch is disabled, and you have enabled *Enable Backend Facet Rendering*, the filtering on the catalogsearch results page will be replaced by facets returned by Algolia.

This feature is currently not compatible with this external module and is still Work In Progress.
19 changes: 19 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "algolia/algoliasearch-magento-2-es-compatibility",
"description": "Algolia Search ES Compatibility module for Magento >=2.3.1|>=2.2.8 and Algolia Search >=1.12 extension",
"type": "magento2-module",
"license": ["MIT"],
"version": "0.0.0",
"require": {
"php": "~7.1.3||~7.2.0",
"algolia/algoliasearch-client-php": ">=1.27.0 <2.0",
"algolia/algoliasearch-magento-2": ">=1.8.0",
"magento/module-elasticsearch": ">=100.2.7"
},
"autoload": {
"files": [ "registration.php" ],
"psr-4": {
"Algolia\\AlgoliaSearchElastic\\": ""
}
}
}
7 changes: 7 additions & 0 deletions etc/di.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">

<preference for="Magento\Elasticsearch\SearchAdapter\Adapter" type="Algolia\AlgoliaSearchElastic\Adapter\AlgoliaElasticSearchAdapter"/>
<preference for="Magento\Elasticsearch\Elasticsearch5\SearchAdapter\Adapter" type="Algolia\AlgoliaSearchElastic\Adapter\AlgoliaElasticSearch5Adapter"/>

</config>
9 changes: 9 additions & 0 deletions etc/module.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?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="Algolia_AlgoliaSearchElastic" setup_version="0.0.0">
<sequence>
<module name="Magento_Elasticsearch"/>
<module name="Algolia_AlgoliaSearch"/>
</sequence>
</module>
</config>
6 changes: 6 additions & 0 deletions registration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Algolia_AlgoliaSearchElastic',
__DIR__
);

0 comments on commit b5f28dc

Please sign in to comment.