Skip to content

Commit cbaca00

Browse files
Merge pull request #53 from daniellienert/task/refactor-suggestions
!!! TASK: Refactor suggestions
2 parents a1650eb + 6b3e0e8 commit cbaca00

6 files changed

Lines changed: 75 additions & 50 deletions

File tree

Classes/Controller/SuggestController.php

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ class SuggestController extends ActionController
4747
'json' => JsonView::class
4848
];
4949

50+
/**
51+
* @Flow\InjectConfiguration("searchAsYouType")
52+
* @var array
53+
*/
54+
protected $searchAsYouTypeSettings = [];
55+
5056
public function initializeObject()
5157
{
5258
if ($this->objectManager->isRegistered(ElasticSearchClient::class)) {
@@ -96,10 +102,11 @@ public function indexAction($term, $contextNodeIdentifier, $dimensionCombination
96102
* @param string $term
97103
* @param string $contextNodeIdentifier
98104
* @param string $dimensionCombination
99-
* @return ElasticSearchQueryBuilder
105+
* @return string
100106
* @throws QueryBuildingException
107+
* @throws \Neos\Flow\Persistence\Exception\IllegalObjectTypeException
101108
*/
102-
protected function buildRequestForTerm($term, $contextNodeIdentifier, $dimensionCombination = null)
109+
protected function buildRequestForTerm($term, $contextNodeIdentifier, $dimensionCombination = null): string
103110
{
104111
$cacheKey = $contextNodeIdentifier . '-' . md5($dimensionCombination);
105112
$termPlaceholder = '---term-soh2gufuNi---';
@@ -113,39 +120,44 @@ protected function buildRequestForTerm($term, $contextNodeIdentifier, $dimension
113120
$contentContext = $this->createContentContext('live', $dimensionCombination ? json_decode($dimensionCombination, true) : []);
114121
$contextNode = $contentContext->getNodeByIdentifier($contextNodeIdentifier);
115122

123+
$sourceFields = $this->searchAsYouTypeSettings['suggestions']['sourceFields'] ?? ['__path'];
124+
116125
/** @var ElasticSearchQueryBuilder $query */
117-
$query = $this->elasticSearchQueryBuilder->query($contextNode);
118-
$query
126+
$query = $this->elasticSearchQueryBuilder
127+
->query($contextNode)
119128
->queryFilter('prefix', [
120129
'__completion' => $termPlaceholder
121130
])
122-
->limit(1)
131+
->limit(0)
123132
->aggregation('autocomplete', [
124133
'terms' => [
125134
'field' => '__completion',
126135
'order' => [
127136
'_count' => 'desc'
128137
],
129-
'include' => [
130-
'pattern' => $termPlaceholder . '.*'
131-
]
138+
'include' => $termPlaceholder . '.*',
139+
'size' => $this->searchAsYouTypeSettings['autocomplete']['size'] ?? 10
132140
]
133141
])
134142
->suggestions('suggestions', [
135143
'prefix' => $termPlaceholder,
136144
'completion' => [
137145
'field' => '__suggestions',
138146
'fuzzy' => true,
139-
'size' => 10,
140-
'context' => [
147+
'size' => $this->searchAsYouTypeSettings['suggestions']['size'] ?? 10,
148+
'contexts' => [
141149
'parentPath' => $contextNode->getPath(),
142150
'workspace' => 'live',
143151
'dimensionCombinationHash' => md5(json_encode($contextNode->getContext()->getDimensions())),
144152
]
145153
]
146154
]);
147155

148-
$requestTemplate = $query->getRequest()->getRequestAsJson();
156+
$request = $query->getRequest()->toArray();
157+
158+
$request['_source'] = $sourceFields;
159+
160+
$requestTemplate = json_encode($request);
149161

150162
$this->elasticSearchQueryTemplateCache->set($contextNodeIdentifier, $requestTemplate);
151163
} else {
@@ -163,26 +175,29 @@ protected function buildRequestForTerm($term, $contextNodeIdentifier, $dimension
163175
*/
164176
protected function extractCompletions($response)
165177
{
166-
$aggregations = isset($response['aggregations']) ? $response['aggregations'] : [];
178+
$aggregations = $response['aggregations'] ?? [];
167179

168-
return array_map(function ($option) {
180+
return array_map(static function ($option) {
169181
return $option['key'];
170182
}, $aggregations['autocomplete']['buckets']);
171183
}
172184

173185
/**
174186
* Extract suggestion options
175187
*
176-
* @param $response
188+
* @param array $response
177189
* @return array
178190
*/
179-
protected function extractSuggestions($response)
191+
protected function extractSuggestions(array $response): array
180192
{
181-
$suggestionOptions = isset($response['suggest']) ? $response['suggest'] : [];
193+
$suggestionOptions = $response['suggest']['suggestions'][0]['options'] ?? [];
182194

183-
if (count($suggestionOptions['suggestions'][0]['options']) > 0) {
184-
return $suggestionOptions['suggestions'][0]['options'];
195+
if (empty($suggestionOptions)) {
196+
return [];
185197
}
186-
return [];
198+
199+
return array_map(static function ($option) {
200+
return $option['_source'];
201+
}, $suggestionOptions);
187202
}
188203
}

Classes/EelHelper/SuggestionIndexHelper.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
<?php
2+
declare(strict_types=1);
3+
24
namespace Flowpack\SearchPlugin\EelHelper;
35

46
/*
@@ -24,10 +26,9 @@ class SuggestionIndexHelper implements ProtectedContextAwareInterface
2426
{
2527
/**
2628
* @param string|array $input The input to store, this can be a an array of strings or just a string. This field is mandatory.
27-
* @param string $output The result is de-duplicated if several documents have the same output, i.e. only one is returned as part of the suggest result.
28-
* @param array $payload An arbitrary JSON object, which is simply returned in the suggest option.
2929
* @param int $weight A positive integer or a string containing a positive integer, which defines a weight and allows you to rank your suggestions.
3030
* @return array
31+
* @throws Exception
3132
*/
3233
public function build($input, $weight = 1)
3334
{
@@ -44,7 +45,7 @@ public function build($input, $weight = 1)
4445
*/
4546
protected function prepareInput($input)
4647
{
47-
$process = function ($input) {
48+
$process = static function ($input) {
4849
if (!\is_string($input)) {
4950
throw new Exception('Only string are supported as input', 1512733297);
5051
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
'Flowpack.SearchPlugin:AutocompletableMixin':
2+
abstract: true
3+
properties:
4+
'__completion':
5+
search:
6+
elasticSearchMapping:
7+
type: text
8+
analyzer: autocomplete
9+
fielddata: true
10+
indexing: "${String.stripTags(q(node).property('title'))}"

Configuration/NodeTypes.Mixins.yaml renamed to Configuration/NodeTypes.Mixin.Suggestable.yaml

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,3 @@
1919
type: category
2020
path: '__dimensionCombinationHash'
2121
indexing: "${Flowpack.SearchPlugin.Suggestion.build(q(node).property('title') ? q(node).property('title') : '', 20)}"
22-
23-
'Flowpack.SearchPlugin:AutocompletableMixin':
24-
abstract: true
25-
properties:
26-
'__completion':
27-
search:
28-
elasticSearchMapping:
29-
type: text
30-
analyzer: autocomplete
31-
fielddata: true
32-
indexing: "${String.stripTags(q(node).property('title'))}"

Configuration/Settings.Neos.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
Neos:
2+
Flow:
3+
mvc:
4+
routes:
5+
'Flowpack.SearchPlugin':
6+
position: 'before Neos.Neos'
7+
Fusion:
8+
defaultContext:
9+
Flowpack.SearchPlugin.Array: Flowpack\SearchPlugin\EelHelper\SearchArrayHelper
10+
Neos:
11+
fusion:
12+
autoInclude:
13+
Flowpack.SearchPlugin: true
14+
ContentRepository:
15+
Search:
16+
defaultContext:
17+
Flowpack.SearchPlugin.Suggestion: Flowpack\SearchPlugin\EelHelper\SuggestionIndexHelper

Configuration/Settings.yaml

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,10 @@
1-
Neos:
2-
Flow:
3-
mvc:
4-
routes:
5-
'Flowpack.SearchPlugin':
6-
position: 'before Neos.Neos'
7-
Fusion:
8-
defaultContext:
9-
Flowpack.SearchPlugin.Array: Flowpack\SearchPlugin\EelHelper\SearchArrayHelper
10-
Neos:
11-
fusion:
12-
autoInclude:
13-
Flowpack.SearchPlugin: true
14-
ContentRepository:
15-
Search:
16-
defaultContext:
17-
Flowpack.SearchPlugin.Suggestion: Flowpack\SearchPlugin\EelHelper\SuggestionIndexHelper
1+
Flowpack:
2+
SearchPlugin:
3+
searchAsYouType:
4+
autocomplete:
5+
size: 10
6+
suggestions:
7+
size: 10
8+
sourceFields:
9+
- __path
10+
- title

0 commit comments

Comments
 (0)