mirror of
https://github.com/Codappix/search_core.git
synced 2024-11-21 21:36:11 +01:00
!!!|FEATURE: Pass facet configuration to search service
Do not limit integrator in possibilities to configure. Therefore previously configure facets for a field need to be adjusted to contain full configuration for elasticsearch. See changelog. Resolves: #120
This commit is contained in:
parent
3bfe55cd33
commit
5d1e7c41bc
13 changed files with 167 additions and 87 deletions
|
@ -45,25 +45,26 @@ class Facet implements FacetInterface
|
|||
*/
|
||||
protected $options = [];
|
||||
|
||||
public function __construct($name, array $aggregation, ConfigurationContainerInterface $configuration)
|
||||
public function __construct(string $name, array $aggregation, ConfigurationContainerInterface $configuration)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->buckets = $aggregation['buckets'];
|
||||
$this->field = $configuration->getIfExists('searching.facets.' . $this->name . '.field') ?: '';
|
||||
|
||||
$config = $configuration->getIfExists('searching.facets.' . $this->name) ?: [];
|
||||
foreach ($config as $configEntry) {
|
||||
if (isset($configEntry['field'])) {
|
||||
$this->field = $configEntry['field'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
public function getName() : string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getField()
|
||||
public function getField() : string
|
||||
{
|
||||
return $this->field;
|
||||
}
|
||||
|
@ -73,7 +74,7 @@ class Facet implements FacetInterface
|
|||
*
|
||||
* @return array<FacetOptionInterface>
|
||||
*/
|
||||
public function getOptions()
|
||||
public function getOptions() : array
|
||||
{
|
||||
$this->initOptions();
|
||||
|
||||
|
|
|
@ -28,15 +28,11 @@ interface FacetRequestInterface
|
|||
/**
|
||||
* The identifier of the facet, used as key in arrays and to get the facet
|
||||
* from search request, etc.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier();
|
||||
public function getIdentifier() : string;
|
||||
|
||||
/**
|
||||
* The field to use for facet building.
|
||||
*
|
||||
* @return string
|
||||
* The config to use for facet building.
|
||||
*/
|
||||
public function getField();
|
||||
public function getConfig() : array;
|
||||
}
|
||||
|
|
|
@ -30,37 +30,27 @@ class FacetRequest implements FacetRequestInterface
|
|||
protected $identifier = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @var array
|
||||
*/
|
||||
protected $field = '';
|
||||
protected $config = [];
|
||||
|
||||
/**
|
||||
* TODO: Add validation / exception?
|
||||
* As the facets come from configuration this might be a good idea to help
|
||||
* integrators find issues.
|
||||
*
|
||||
* @param string $identifier
|
||||
* @param string $field
|
||||
*/
|
||||
public function __construct($identifier, $field)
|
||||
public function __construct(string $identifier, array $config)
|
||||
{
|
||||
$this->identifier = $identifier;
|
||||
$this->field = $field;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier()
|
||||
public function getIdentifier() : string
|
||||
{
|
||||
return $this->identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getField()
|
||||
public function getConfig() : array
|
||||
{
|
||||
return $this->field;
|
||||
return $this->config;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -239,11 +239,7 @@ class QueryFactory
|
|||
foreach ($searchRequest->getFacets() as $facet) {
|
||||
$query = ArrayUtility::arrayMergeRecursiveOverrule($query, [
|
||||
'aggs' => [
|
||||
$facet->getIdentifier() => [
|
||||
'terms' => [
|
||||
'field' => $facet->getField(),
|
||||
],
|
||||
],
|
||||
$facet->getIdentifier() => $facet->getConfig(),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -103,15 +103,10 @@ class SearchService
|
|||
}
|
||||
|
||||
foreach ($facetsConfig as $identifier => $facetConfig) {
|
||||
if (!isset($facetConfig['field']) || trim($facetConfig['field']) === '') {
|
||||
// TODO: Finish throw
|
||||
throw new \Exception('message', 1499171142);
|
||||
}
|
||||
|
||||
$searchRequest->addFacet($this->objectManager->get(
|
||||
FacetRequest::class,
|
||||
$identifier,
|
||||
$facetConfig['field']
|
||||
$facetConfig
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
8
Documentation/source/changelog.rst
Normal file
8
Documentation/source/changelog.rst
Normal file
|
@ -0,0 +1,8 @@
|
|||
Changelog
|
||||
=========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:glob:
|
||||
|
||||
changelog/*
|
|
@ -0,0 +1,40 @@
|
|||
Breacking Change 120 "Pass facets configuration to elasticsearch"
|
||||
=================================================================
|
||||
|
||||
In order to allow arbitrary facet configuration, we do not process the facet configuration anymore.
|
||||
Instead integrators are able to configure facets for search service "as is". We just pipe the
|
||||
configuration through.
|
||||
|
||||
Therefore the following, which worked before, does not work anymore:
|
||||
|
||||
.. code-block:: typoscript
|
||||
:linenos:
|
||||
:emphasize-lines: 4
|
||||
|
||||
plugin.tx_searchcore.settings.search {
|
||||
facets {
|
||||
category {
|
||||
field = categories
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Instead you have to provide the full configuration yourself:
|
||||
|
||||
.. code-block:: typoscript
|
||||
:linenos:
|
||||
:emphasize-lines: 4,6
|
||||
|
||||
plugin.tx_searchcore.settings.search {
|
||||
facets {
|
||||
category {
|
||||
terms {
|
||||
field = categories
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
You need to add line 4 and 6, the additional level ``terms`` for elasticsearch.
|
||||
|
||||
See :issue:`120`.
|
|
@ -15,3 +15,4 @@ Table of Contents
|
|||
connections
|
||||
indexer
|
||||
development
|
||||
changelog
|
||||
|
|
75
Tests/Functional/Connection/Elasticsearch/FacetTest.php
Normal file
75
Tests/Functional/Connection/Elasticsearch/FacetTest.php
Normal file
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
namespace Codappix\SearchCore\Tests\Functional\Connection\Elasticsearch;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
use Codappix\SearchCore\Domain\Index\IndexerFactory;
|
||||
use Codappix\SearchCore\Domain\Model\SearchRequest;
|
||||
use Codappix\SearchCore\Domain\Search\SearchService;
|
||||
use TYPO3\CMS\Extbase\Object\ObjectManager;
|
||||
|
||||
class FacetTest extends AbstractFunctionalTestCase
|
||||
{
|
||||
protected function getTypoScriptFilesForFrontendRootPage()
|
||||
{
|
||||
return array_merge(parent::getTypoScriptFilesForFrontendRootPage(), ['EXT:search_core/Tests/Functional/Fixtures/Searching/Facet.ts']);
|
||||
}
|
||||
|
||||
protected function getDataSets()
|
||||
{
|
||||
return array_merge(
|
||||
parent::getDataSets(),
|
||||
['Tests/Functional/Fixtures/Searching/Filter.xml']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function itsPossibleToFetchFacetsForField()
|
||||
{
|
||||
\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(ObjectManager::class)
|
||||
->get(IndexerFactory::class)
|
||||
->getIndexer('tt_content')
|
||||
->indexAllDocuments()
|
||||
;
|
||||
|
||||
$searchService = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(ObjectManager::class)
|
||||
->get(SearchService::class);
|
||||
|
||||
$searchRequest = new SearchRequest();
|
||||
$result = $searchService->search($searchRequest);
|
||||
|
||||
$this->assertSame(1, count($result->getFacets()), 'Did not receive the single defined facet.');
|
||||
|
||||
$facet = current($result->getFacets());
|
||||
$this->assertSame('contentTypes', $facet->getName(), 'Name of facet was not as expected.');
|
||||
$this->assertSame('CType', $facet->getField(), 'Field of facet was not expected.');
|
||||
|
||||
$options = $facet->getOptions();
|
||||
$this->assertSame(2, count($options), 'Did not receive the expected number of possible options for facet.');
|
||||
$option = $options['HTML'];
|
||||
$this->assertSame('HTML', $option->getName(), 'Option did not have expected Name.');
|
||||
$this->assertSame(1, $option->getCount(), 'Option did not have expected count.');
|
||||
$option = $options['Header'];
|
||||
$this->assertSame('Header', $option->getName(), 'Option did not have expected Name.');
|
||||
$this->assertSame(1, $option->getCount(), 'Option did not have expected count.');
|
||||
}
|
||||
}
|
|
@ -58,37 +58,4 @@ class FilterTest extends AbstractFunctionalTestCase
|
|||
$this->assertSame(5, $result->getResults()[0]['uid'], 'Did not get the expected result entry.');
|
||||
$this->assertSame(1, count($result), 'Did not receive the single filtered element.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function itsPossibleToFetchFacetsForField()
|
||||
{
|
||||
\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(ObjectManager::class)
|
||||
->get(IndexerFactory::class)
|
||||
->getIndexer('tt_content')
|
||||
->indexAllDocuments()
|
||||
;
|
||||
|
||||
$searchService = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(ObjectManager::class)
|
||||
->get(SearchService::class);
|
||||
|
||||
$searchRequest = new SearchRequest('Search Word');
|
||||
$result = $searchService->search($searchRequest);
|
||||
|
||||
$this->assertSame(1, count($result->getFacets()), 'Did not receive the single defined facet.');
|
||||
|
||||
$facet = current($result->getFacets());
|
||||
$this->assertSame('contentTypes', $facet->getName(), 'Name of facet was not as expected.');
|
||||
$this->assertSame('CType', $facet->getField(), 'Field of facet was not expected.');
|
||||
|
||||
$options = $facet->getOptions();
|
||||
$this->assertSame(2, count($options), 'Did not receive the expected number of possible options for facet.');
|
||||
$option = $options['HTML'];
|
||||
$this->assertSame('HTML', $option->getName(), 'Option did not have expected Name.');
|
||||
$this->assertSame(1, $option->getCount(), 'Option did not have expected count.');
|
||||
$option = $options['Header'];
|
||||
$this->assertSame('Header', $option->getName(), 'Option did not have expected Name.');
|
||||
$this->assertSame(1, $option->getCount(), 'Option did not have expected count.');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,12 +37,6 @@ plugin {
|
|||
}
|
||||
|
||||
searching {
|
||||
facets {
|
||||
contentTypes {
|
||||
field = CType
|
||||
}
|
||||
}
|
||||
|
||||
fields {
|
||||
query = _all
|
||||
}
|
||||
|
|
17
Tests/Functional/Fixtures/Searching/Facet.ts
Normal file
17
Tests/Functional/Fixtures/Searching/Facet.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
plugin {
|
||||
tx_searchcore {
|
||||
settings {
|
||||
searching {
|
||||
facets {
|
||||
contentTypes {
|
||||
terms {
|
||||
field = CType
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.tx_searchcore < plugin.tx_searchcore
|
|
@ -118,8 +118,8 @@ class QueryFactoryTest extends AbstractUnitTestCase
|
|||
{
|
||||
$this->configureConfigurationMockWithDefault();
|
||||
$searchRequest = new SearchRequest('SearchWord');
|
||||
$searchRequest->addFacet(new FacetRequest('Identifier', 'FieldName'));
|
||||
$searchRequest->addFacet(new FacetRequest('Identifier 2', 'FieldName 2'));
|
||||
$searchRequest->addFacet(new FacetRequest('Identifier', ['terms' => ['field' => 'FieldName']]));
|
||||
$searchRequest->addFacet(new FacetRequest('Identifier 2', ['terms' => ['field' => 'FieldName 2']]));
|
||||
|
||||
$query = $this->subject->create($searchRequest);
|
||||
$this->assertSame(
|
||||
|
|
Loading…
Reference in a new issue