-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Discoverer v2 support. Spelling suggestions feature (#7)
- Loading branch information
1 parent
c9b9f5c
commit 89ee60e
Showing
15 changed files
with
301 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--- | ||
Name: discoverer-bifrost-adaptors | ||
After: discoverer-adaptors | ||
Only: | ||
envvarset: 'BIFROST_QUERY_API_KEY' | ||
--- | ||
SilverStripe\Core\Injector\Injector: | ||
# Adaptors provided by this module | ||
SilverStripe\Discoverer\Service\Interfaces\QuerySuggestionAdaptor: | ||
class: SilverStripe\DiscovererBifrost\Service\Adaptors\QuerySuggestionAdaptor | ||
SilverStripe\Discoverer\Service\Interfaces\SpellingSuggestionAdaptor: | ||
class: SilverStripe\DiscovererBifrost\Service\Adaptors\SpellingSuggestionAdaptor | ||
# Adaptors provided by the ElasticEnterprise dependency | ||
SilverStripe\Discoverer\Query\Facet\FacetAdaptor: | ||
class: SilverStripe\DiscovererElasticEnterprise\Query\Facet\FacetAdaptor | ||
SilverStripe\Discoverer\Query\Filter\CriteriaAdaptor: | ||
class: SilverStripe\DiscovererElasticEnterprise\Query\Filter\CriteriaAdaptor | ||
SilverStripe\Discoverer\Query\Filter\CriterionAdaptor: | ||
class: SilverStripe\DiscovererElasticEnterprise\Query\Filter\CriterionAdaptor | ||
SilverStripe\Discoverer\Service\Interfaces\ProcessAnalyticsAdaptor: | ||
class: SilverStripe\DiscovererElasticEnterprise\Service\Adaptors\ProcessAnalyticsAdaptor | ||
SilverStripe\Discoverer\Service\Interfaces\SearchAdaptor: | ||
class: SilverStripe\DiscovererElasticEnterprise\Service\Adaptors\SearchAdaptor | ||
|
||
SilverStripe\DiscovererElasticEnterprise\Service\Adaptors\BaseAdaptor: | ||
prefix_env_var: 'BIFROST_ENGINE_PREFIX' |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--- | ||
Name: discoverer-bifrost-factory | ||
Only: | ||
envvarset: 'BIFROST_QUERY_API_KEY' | ||
--- | ||
SilverStripe\Core\Injector\Injector: | ||
Elastic\EnterpriseSearch\Client.searchClient: | ||
factory: SilverStripe\DiscovererBifrost\Service\ClientFactory | ||
constructor: | ||
host: '`BIFROST_ENDPOINT`' | ||
token: '`BIFROST_QUERY_API_KEY`' | ||
http_client: '%$GuzzleHttp\Client' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
--- | ||
Name: discoverer-bifrost-requests | ||
Only: | ||
envvarset: 'BIFROST_QUERY_API_KEY' | ||
--- | ||
SilverStripe\Core\Injector\Injector: | ||
Elastic\EnterpriseSearch\AppSearch\Request\Search: | ||
class: SilverStripe\DiscovererBifrost\Service\Requests\Search | ||
Elastic\EnterpriseSearch\AppSearch\Request\LogClickthrough: | ||
class: SilverStripe\DiscovererBifrost\Service\Requests\ClickPost |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<?php | ||
|
||
namespace SilverStripe\DiscovererBifrost\Processors; | ||
|
||
use SilverStripe\Core\Injector\Injectable; | ||
use SilverStripe\Discoverer\Query\Suggestion; | ||
use SilverStripe\DiscovererBifrost\Service\Requests\Params\SuggestionParams; | ||
|
||
class SuggestionParamsProcessor | ||
{ | ||
|
||
use Injectable; | ||
|
||
public function getQueryParams(Suggestion $suggestion): SuggestionParams | ||
{ | ||
$suggestionParams = SuggestionParams::create(); | ||
$suggestionParams->query = $suggestion->getQueryString(); | ||
$suggestionParams->formatted = $suggestion->isFormatted(); | ||
|
||
$limit = $suggestion->getLimit(); | ||
$fields = $suggestion->getFields(); | ||
|
||
if ($limit) { | ||
$suggestionParams->size = $limit; | ||
} | ||
|
||
if ($fields) { | ||
$suggestionParams->fields = $fields; | ||
} | ||
|
||
return $suggestionParams; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<?php | ||
|
||
namespace SilverStripe\DiscovererBifrost\Processors; | ||
|
||
use Exception; | ||
use SilverStripe\Core\Injector\Injectable; | ||
use SilverStripe\Discoverer\Service\Results\Field; | ||
use SilverStripe\Discoverer\Service\Results\Suggestions; | ||
|
||
class SuggestionsProcessor | ||
{ | ||
|
||
use Injectable; | ||
|
||
/** | ||
* @throws Exception | ||
*/ | ||
public function getProcessedSuggestions(Suggestions $suggestions, array $response): void | ||
{ | ||
// Check that we have all critical fields in our Elastic response | ||
$this->validateResponse($response); | ||
|
||
$results = $response['results'] ?? []; | ||
|
||
foreach ($results as $result) { | ||
$suggestions->addSuggestion(Field::create( | ||
$result['raw'] ?? null, | ||
$result['snippet'] ?? null, | ||
)); | ||
} | ||
} | ||
|
||
private function validateResponse(array $response): void | ||
{ | ||
// If any errors are present, then let's throw and track what they were | ||
if (array_key_exists('errors', $response)) { | ||
throw new Exception(sprintf('Elastic response contained errors: %s', json_encode($response['errors']))); | ||
} | ||
|
||
// The top level fields that we expect to receive from Elastic for each search | ||
$results = $response['results'] ?? null; | ||
|
||
// Specifically checking is_array(), because an empty results array is a valid response | ||
if (!is_array($results)) { | ||
throw new Exception('Missing required top level fields for query suggestions: results'); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
<?php | ||
|
||
namespace SilverStripe\DiscovererBifrost\Service\Adaptors; | ||
|
||
use Elastic\EnterpriseSearch\Exception\ClientErrorResponseException; | ||
use Elastic\EnterpriseSearch\Response\Response; | ||
use SilverStripe\Core\Injector\Injector; | ||
use SilverStripe\Discoverer\Query\Suggestion; | ||
use SilverStripe\Discoverer\Service\Interfaces\QuerySuggestionAdaptor as QuerySuggestionAdaptorInterface; | ||
use SilverStripe\Discoverer\Service\Results\Suggestions; | ||
use SilverStripe\DiscovererBifrost\Processors\SuggestionParamsProcessor; | ||
use SilverStripe\DiscovererBifrost\Processors\SuggestionsProcessor; | ||
use SilverStripe\DiscovererBifrost\Service\Requests\QuerySuggestion; | ||
use SilverStripe\DiscovererElasticEnterprise\Service\Adaptors\BaseAdaptor; | ||
use Throwable; | ||
|
||
class QuerySuggestionAdaptor extends BaseAdaptor implements QuerySuggestionAdaptorInterface | ||
{ | ||
|
||
public function process(Suggestion $suggestion, string $indexName): Suggestions | ||
{ | ||
// Instantiate our Suggestions class with empty data. This will still be returned if there is an Exception | ||
// during communication with Elastic (so that the page doesn't seriously break) | ||
$suggestions = Suggestions::create(); | ||
|
||
try { | ||
$engine = $this->environmentizeIndex($indexName); | ||
$params = SuggestionParamsProcessor::singleton()->getQueryParams($suggestion); | ||
$request = QuerySuggestion::create($engine, $params); | ||
|
||
$transportResponse = $this->getClient()->appSearch()->getTransport()->sendRequest($request->getRequest()); | ||
$response = Injector::inst()->create(Response::class, $transportResponse); | ||
|
||
SuggestionsProcessor::singleton()->getProcessedSuggestions($suggestions, $response->asArray()); | ||
// If we got this far, then the request was a success | ||
$suggestions->setSuccess(true); | ||
} catch (ClientErrorResponseException $e) { | ||
$errors = (string) $e->getResponse()->getBody(); | ||
// Log the error without breaking the page | ||
$this->getLogger()->error(sprintf('Bifrost error: %s', $errors), ['bifrost' => $e]); | ||
// Our request was not a success | ||
$suggestions->setSuccess(false); | ||
} catch (Throwable $e) { | ||
// Log the error without breaking the page | ||
$this->getLogger()->error(sprintf('Bifrost error: %s', $e->getMessage()), ['bifrost' => $e]); | ||
// Our request was not a success | ||
$suggestions->setSuccess(false); | ||
} finally { | ||
return $suggestions; | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
<?php | ||
|
||
namespace SilverStripe\DiscovererBifrost\Service\Adaptors; | ||
|
||
use Elastic\EnterpriseSearch\Exception\ClientErrorResponseException; | ||
use Elastic\EnterpriseSearch\Response\Response; | ||
use SilverStripe\Core\Injector\Injector; | ||
use SilverStripe\Discoverer\Query\Suggestion; | ||
use SilverStripe\Discoverer\Service\Interfaces\SpellingSuggestionAdaptor as SpellingSuggestionAdaptorInterface; | ||
use SilverStripe\Discoverer\Service\Results\Suggestions; | ||
use SilverStripe\DiscovererBifrost\Processors\SuggestionParamsProcessor; | ||
use SilverStripe\DiscovererBifrost\Processors\SuggestionsProcessor; | ||
use SilverStripe\DiscovererBifrost\Service\Requests\SpellingSuggestion; | ||
use SilverStripe\DiscovererElasticEnterprise\Service\Adaptors\BaseAdaptor; | ||
use Throwable; | ||
|
||
class SpellingSuggestionAdaptor extends BaseAdaptor implements SpellingSuggestionAdaptorInterface | ||
{ | ||
|
||
public function process(Suggestion $suggestion, string $indexName): Suggestions | ||
{ | ||
// Instantiate our Suggestions class with empty data. This will still be returned if there is an Exception | ||
// during communication with Elastic (so that the page doesn't seriously break) | ||
$suggestions = Suggestions::create(); | ||
|
||
try { | ||
$engine = $this->environmentizeIndex($indexName); | ||
$params = SuggestionParamsProcessor::singleton()->getQueryParams($suggestion); | ||
$request = SpellingSuggestion::create($engine, $params); | ||
|
||
$transportResponse = $this->getClient()->appSearch()->getTransport()->sendRequest($request->getRequest()); | ||
$response = Injector::inst()->create(Response::class, $transportResponse); | ||
|
||
SuggestionsProcessor::singleton()->getProcessedSuggestions($suggestions, $response->asArray()); | ||
// If we got this far, then the request was a success | ||
$suggestions->setSuccess(true); | ||
} catch (ClientErrorResponseException $e) { | ||
$errors = (string) $e->getResponse()->getBody(); | ||
// Log the error without breaking the page | ||
$this->getLogger()->error(sprintf('Bifrost error: %s', $errors), ['bifrost' => $e]); | ||
// Our request was not a success | ||
$suggestions->setSuccess(false); | ||
} catch (Throwable $e) { | ||
// Log the error without breaking the page | ||
$this->getLogger()->error(sprintf('Bifrost error: %s', $e->getMessage()), ['bifrost' => $e]); | ||
// Our request was not a success | ||
$suggestions->setSuccess(false); | ||
} finally { | ||
return $suggestions; | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<?php | ||
|
||
namespace SilverStripe\DiscovererBifrost\Service\Requests\Params; | ||
|
||
use SilverStripe\Core\Injector\Injectable; | ||
|
||
/** | ||
* The Elastic requests that we use turn properties into arguments for the request, so we are stuck with this paradigm | ||
* for now | ||
* | ||
* @phpcs:disable SlevomatCodingStandard.Classes.ForbiddenPublicProperty.ForbiddenPublicProperty | ||
*/ | ||
class SuggestionParams | ||
{ | ||
|
||
use Injectable; | ||
|
||
public ?string $query = null; | ||
|
||
public array $fields = []; | ||
|
||
public ?int $size = null; | ||
|
||
public bool $formatted = false; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<?php | ||
|
||
namespace SilverStripe\DiscovererBifrost\Service\Requests; | ||
|
||
use Elastic\EnterpriseSearch\Request\Request; | ||
use SilverStripe\Core\Injector\Injectable; | ||
use SilverStripe\DiscovererBifrost\Service\Requests\Params\SuggestionParams; | ||
|
||
class SpellingSuggestion extends Request | ||
{ | ||
|
||
use Injectable; | ||
|
||
public function __construct(string $engineName, SuggestionParams $params) | ||
{ | ||
$this->method = 'POST'; | ||
$this->path = sprintf('/api/v1/%s/spelling_suggestion', $engineName); | ||
$this->headers['Content-Type'] = 'application/json'; | ||
$this->body = $params; | ||
} | ||
|
||
} |