Skip to content

Commit 716dca6

Browse files
author
Alexander Akimov
authored
Merge pull request #3043 from magento-tsg/2.3-develop-pr32
[TSG] Upporting for 2.3 (pr32) (2.3.0)
2 parents 5084541 + a88d4d4 commit 716dca6

File tree

13 files changed

+667
-12
lines changed

13 files changed

+667
-12
lines changed

app/code/Magento/Elasticsearch/Elasticsearch5/Model/Client/Elasticsearch.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ public function addFieldsMapping(array $fields, $index, $entityType)
258258
'match_mapping_type' => 'string',
259259
'mapping' => [
260260
'type' => 'float',
261+
'store' => true,
261262
],
262263
],
263264
],
Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Elasticsearch\Elasticsearch5\SearchAdapter\Aggregation;
9+
10+
use Magento\Framework\Search\Dynamic\IntervalInterface;
11+
use Magento\Elasticsearch\SearchAdapter\ConnectionManager;
12+
use Magento\Elasticsearch\Model\Adapter\FieldMapperInterface;
13+
use Magento\Elasticsearch\Model\Config;
14+
use Magento\Elasticsearch\SearchAdapter\SearchIndexNameResolver;
15+
use Magento\CatalogSearch\Model\Indexer\Fulltext;
16+
17+
/**
18+
* Aggregate price intervals for search query result.
19+
*/
20+
class Interval implements IntervalInterface
21+
{
22+
/**
23+
* Minimal possible value
24+
*/
25+
const DELTA = 0.005;
26+
27+
/**
28+
* @var ConnectionManager
29+
*/
30+
private $connectionManager;
31+
32+
/**
33+
* @var FieldMapperInterface
34+
*/
35+
private $fieldMapper;
36+
37+
/**
38+
* @var Config
39+
*/
40+
private $clientConfig;
41+
42+
/**
43+
* @var string
44+
*/
45+
private $fieldName;
46+
47+
/**
48+
* @var string
49+
*/
50+
private $storeId;
51+
52+
/**
53+
* @var array
54+
*/
55+
private $entityIds;
56+
57+
/**
58+
* @var SearchIndexNameResolver
59+
*/
60+
private $searchIndexNameResolver;
61+
62+
/**
63+
* @param ConnectionManager $connectionManager
64+
* @param FieldMapperInterface $fieldMapper
65+
* @param Config $clientConfig
66+
* @param SearchIndexNameResolver $searchIndexNameResolver
67+
* @param string $fieldName
68+
* @param string $storeId
69+
* @param array $entityIds
70+
*/
71+
public function __construct(
72+
ConnectionManager $connectionManager,
73+
FieldMapperInterface $fieldMapper,
74+
Config $clientConfig,
75+
SearchIndexNameResolver $searchIndexNameResolver,
76+
string $fieldName,
77+
string $storeId,
78+
array $entityIds
79+
) {
80+
$this->connectionManager = $connectionManager;
81+
$this->fieldMapper = $fieldMapper;
82+
$this->clientConfig = $clientConfig;
83+
$this->fieldName = $fieldName;
84+
$this->storeId = $storeId;
85+
$this->entityIds = $entityIds;
86+
$this->searchIndexNameResolver = $searchIndexNameResolver;
87+
}
88+
89+
/**
90+
* {@inheritdoc}
91+
*/
92+
public function load($limit, $offset = null, $lower = null, $upper = null)
93+
{
94+
$from = $to = [];
95+
if ($lower) {
96+
$from = ['gte' => $lower - self::DELTA];
97+
}
98+
if ($upper) {
99+
$to = ['lt' => $upper - self::DELTA];
100+
}
101+
102+
$requestQuery = $this->prepareBaseRequestQuery($from, $to);
103+
$requestQuery = array_merge_recursive(
104+
$requestQuery,
105+
['body' => ['stored_fields' => [$this->fieldName], 'size' => $limit]]
106+
);
107+
108+
if ($offset) {
109+
$requestQuery['body']['from'] = $offset;
110+
}
111+
112+
$queryResult = $this->connectionManager->getConnection()
113+
->query($requestQuery);
114+
115+
return $this->arrayValuesToFloat($queryResult['hits']['hits'], $this->fieldName);
116+
}
117+
118+
/**
119+
* {@inheritdoc}
120+
*/
121+
public function loadPrevious($data, $index, $lower = null)
122+
{
123+
if ($lower) {
124+
$from = ['gte' => $lower - self::DELTA];
125+
}
126+
if ($data) {
127+
$to = ['lt' => $data - self::DELTA];
128+
}
129+
130+
$requestQuery = $this->prepareBaseRequestQuery($from, $to);
131+
$requestQuery = array_merge_recursive(
132+
$requestQuery,
133+
['size' => 0]
134+
);
135+
136+
$queryResult = $this->connectionManager->getConnection()
137+
->query($requestQuery);
138+
139+
$offset = $queryResult['hits']['total'];
140+
if (!$offset) {
141+
return false;
142+
}
143+
144+
return $this->load($index - $offset + 1, $offset - 1, $lower);
145+
}
146+
147+
/**
148+
* {@inheritdoc}
149+
*/
150+
public function loadNext($data, $rightIndex, $upper = null)
151+
{
152+
$from = ['gt' => $data + self::DELTA];
153+
$to = ['lt' => $data - self::DELTA];
154+
155+
$requestCountQuery = $this->prepareBaseRequestQuery($from, $to);
156+
$requestCountQuery = array_merge_recursive(
157+
$requestCountQuery,
158+
['size' => 0]
159+
);
160+
161+
$queryCountResult = $this->connectionManager->getConnection()
162+
->query($requestCountQuery);
163+
164+
$offset = $queryCountResult['hits']['total'];
165+
if (!$offset) {
166+
return false;
167+
}
168+
169+
$from = ['gte' => $data - self::DELTA];
170+
if ($upper !== null) {
171+
$to = ['lt' => $data - self::DELTA];
172+
}
173+
174+
$requestQuery = $requestCountQuery;
175+
176+
$requestCountQuery['body']['query']['bool']['filter']['bool']['must']['range'] =
177+
[$this->fieldName => array_merge($from, $to)];
178+
$requestCountQuery['body']['from'] = $offset - 1;
179+
$requestCountQuery['body']['size'] = $rightIndex - $offset + 1;
180+
$queryResult = $this->connectionManager->getConnection()
181+
->query($requestQuery);
182+
183+
return array_reverse($this->arrayValuesToFloat($queryResult['hits']['hits'], $this->fieldName));
184+
}
185+
186+
/**
187+
* Conver array values to float type.
188+
*
189+
* @param array $hits
190+
* @param string $fieldName
191+
*
192+
* @return float[]
193+
*/
194+
private function arrayValuesToFloat(array $hits, string $fieldName): array
195+
{
196+
$returnPrices = [];
197+
foreach ($hits as $hit) {
198+
$returnPrices[] = (float)$hit['fields'][$fieldName][0];
199+
}
200+
201+
return $returnPrices;
202+
}
203+
204+
/**
205+
* Prepare base query for search.
206+
*
207+
* @param array|null $from
208+
* @param array|null $to
209+
* @return array
210+
*/
211+
private function prepareBaseRequestQuery($from = null, $to = null): array
212+
{
213+
$requestQuery = [
214+
'index' => $this->searchIndexNameResolver->getIndexName($this->storeId, Fulltext::INDEXER_ID),
215+
'type' => $this->clientConfig->getEntityType(),
216+
'body' => [
217+
'stored_fields' => [
218+
'_id',
219+
],
220+
'query' => [
221+
'bool' => [
222+
'must' => [
223+
'match_all' => new \stdClass(),
224+
],
225+
'filter' => [
226+
'bool' => [
227+
'must' => [
228+
[
229+
'terms' => [
230+
'_id' => $this->entityIds,
231+
],
232+
],
233+
[
234+
'range' => [
235+
$this->fieldName => array_merge($from, $to),
236+
],
237+
],
238+
],
239+
],
240+
],
241+
],
242+
],
243+
'sort' => [
244+
$this->fieldName,
245+
],
246+
],
247+
];
248+
249+
return $requestQuery;
250+
}
251+
}

app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Client/ElasticsearchTest.php

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ public function testAddFieldsMapping()
343343
'product' => [
344344
'_all' => [
345345
'enabled' => true,
346-
'type' => 'text'
346+
'type' => 'text',
347347
],
348348
'properties' => [
349349
'name' => [
@@ -356,7 +356,8 @@ public function testAddFieldsMapping()
356356
'match' => 'price_*',
357357
'match_mapping_type' => 'string',
358358
'mapping' => [
359-
'type' => 'float'
359+
'type' => 'float',
360+
'store' => true,
360361
],
361362
],
362363
],
@@ -366,7 +367,7 @@ public function testAddFieldsMapping()
366367
'match_mapping_type' => 'string',
367368
'mapping' => [
368369
'type' => 'text',
369-
'index' => 'no'
370+
'index' => 'no',
370371
],
371372
],
372373
],
@@ -375,7 +376,7 @@ public function testAddFieldsMapping()
375376
'match' => 'position_*',
376377
'match_mapping_type' => 'string',
377378
'mapping' => [
378-
'type' => 'int'
379+
'type' => 'int',
379380
],
380381
],
381382
],
@@ -409,7 +410,7 @@ public function testAddFieldsMappingFailure()
409410
'product' => [
410411
'_all' => [
411412
'enabled' => true,
412-
'type' => 'text'
413+
'type' => 'text',
413414
],
414415
'properties' => [
415416
'name' => [
@@ -422,7 +423,8 @@ public function testAddFieldsMappingFailure()
422423
'match' => 'price_*',
423424
'match_mapping_type' => 'string',
424425
'mapping' => [
425-
'type' => 'float'
426+
'type' => 'float',
427+
'store' => true,
426428
],
427429
],
428430
],
@@ -441,7 +443,7 @@ public function testAddFieldsMappingFailure()
441443
'match' => 'position_*',
442444
'match_mapping_type' => 'string',
443445
'mapping' => [
444-
'type' => 'int'
446+
'type' => 'int',
445447
],
446448
],
447449
],

0 commit comments

Comments
 (0)