Skip to content

Commit a8a7d27

Browse files
committed
MAGETWO-91813: Elasticsearch incorrect results relevance score
1 parent fe11b39 commit a8a7d27

File tree

4 files changed

+331
-13
lines changed

4 files changed

+331
-13
lines changed

app/code/Magento/Elasticsearch/Elasticsearch5/Model/Adapter/FieldMapper/ProductFieldMapper.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,14 @@ protected function isAttributeUsedInAdvancedSearch($attribute)
173173
*/
174174
protected function getRefinedFieldName($frontendInput, $fieldType, $attributeCode)
175175
{
176-
return (in_array($frontendInput, ['select', 'boolean'], true) && $fieldType === 'integer')
177-
? $attributeCode . '_value' : $attributeCode;
176+
switch ($frontendInput) {
177+
case 'select':
178+
return in_array($fieldType, ['text','integer'], true) ? $attributeCode . '_value' : $attributeCode;
179+
case 'boolean':
180+
return $fieldType === 'integer' ? $attributeCode . '_value' : $attributeCode;
181+
default:
182+
return $attributeCode;
183+
}
178184
}
179185

180186
/**

app/code/Magento/Elasticsearch/Model/Adapter/FieldMapper/ProductFieldMapper.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,22 @@ public function getAllAttributesTypes($context = [])
115115

116116
return $allAttributes;
117117
}
118+
119+
/**
120+
* @param string $frontendInput
121+
* @param string $fieldType
122+
* @param string $attributeCode
123+
* @return string
124+
*/
125+
protected function getRefinedFieldName($frontendInput, $fieldType, $attributeCode)
126+
{
127+
switch ($frontendInput) {
128+
case 'select':
129+
return in_array($fieldType, ['string','integer'], true) ? $attributeCode . '_value' : $attributeCode;
130+
case 'boolean':
131+
return $fieldType === 'integer' ? $attributeCode . '_value' : $attributeCode;
132+
default:
133+
return $attributeCode;
134+
}
135+
}
118136
}

app/code/Magento/Elasticsearch/Test/Unit/Elasticsearch5/Model/Adapter/FieldMapper/ProductFieldMapperTest.php

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -227,17 +227,17 @@ public function testGetAllAttributesTypes($attributeCode, $inputType, $searchAtt
227227
public function attributeCodeProvider()
228228
{
229229
return [
230-
['id', 'id', 'string'],
231-
['status', 'status', 'string'],
232-
['status', 'status', 'string', ['type'=>'default']],
233-
['price', 'price_0_1', 'string', ['type'=>'default']],
234-
['position', 'position_category_1', 'string', ['type'=>'default']],
235-
['price', 'price_2_3', 'string', ['type'=>'default', 'customerGroupId'=>'2', 'websiteId'=>'3']],
236-
['position', 'position_category_3', 'string', ['type'=>'default', 'categoryId'=>'3']],
237-
['color', 'color', 'select', ['type'=>'default']],
238-
['description', 'sort_description', 'string', ['type'=>'some']],
239-
['*', '_all', 'string', ['type'=>'text']],
240-
['description', 'description', 'string', ['type'=>'text']],
230+
['id', 'id', 'text'],
231+
['status', 'status', 'text'],
232+
['status', 'status_value', 'text', ['type'=>'default']],
233+
['price', 'price_0_1', 'text', ['type'=>'default']],
234+
['position', 'position_category_1', 'text', ['type'=>'default']],
235+
['price', 'price_2_3', 'text', ['type'=>'default', 'customerGroupId'=>'2', 'websiteId'=>'3']],
236+
['position', 'position_category_3', 'text', ['type'=>'default', 'categoryId'=>'3']],
237+
['color', 'color_value', 'text', ['type'=>'text']],
238+
['description', 'sort_description', 'text', ['type'=>'some']],
239+
['*', '_all', 'text', ['type'=>'text']],
240+
['description', 'description_value', 'text', ['type'=>'text']],
241241
];
242242
}
243243

Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Elasticsearch\Test\Unit\Model\Adapter\FieldMapper;
7+
8+
use Magento\Catalog\Api\Data\ProductAttributeInterface;
9+
use Magento\Elasticsearch\Model\Adapter\FieldType;
10+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
11+
12+
class ProductFieldMapperTest extends \PHPUnit\Framework\TestCase
13+
{
14+
/**
15+
* @var \Magento\Elasticsearch\Model\Adapter\FieldMapper\ProductFieldMapper
16+
*/
17+
protected $mapper;
18+
19+
/**
20+
* @var \Magento\Eav\Model\Config|\PHPUnit_Framework_MockObject_MockObject
21+
*/
22+
protected $eavConfig;
23+
24+
/**
25+
* @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject
26+
*/
27+
protected $coreRegistry;
28+
29+
/**
30+
* @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject
31+
*/
32+
protected $customerSession;
33+
34+
/**
35+
* @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject
36+
*/
37+
protected $storeManager;
38+
39+
/**
40+
* @var \Magento\Catalog\Model\ResourceModel\Eav\Attribute|\PHPUnit_Framework_MockObject_MockObject
41+
*/
42+
protected $eavAttributeResource;
43+
44+
/**
45+
* @var FieldType|\PHPUnit_Framework_MockObject_MockObject
46+
*/
47+
protected $fieldType;
48+
49+
/**
50+
* @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject
51+
*/
52+
protected $store;
53+
54+
/**
55+
* Set up test environment
56+
*
57+
* @return void
58+
*/
59+
protected function setUp()
60+
{
61+
$this->eavConfig = $this->getMockBuilder(\Magento\Eav\Model\Config::class)
62+
->disableOriginalConstructor()
63+
->setMethods(['getEntityType', 'getAttribute', 'getEntityAttributeCodes'])
64+
->getMock();
65+
66+
$this->fieldType = $this->getMockBuilder(FieldType::class)
67+
->disableOriginalConstructor()
68+
->setMethods(['getFieldType'])
69+
->getMock();
70+
71+
$this->customerSession = $this->getMockBuilder(\Magento\Customer\Model\Session::class)
72+
->disableOriginalConstructor()
73+
->setMethods(['getCustomerGroupId'])
74+
->getMock();
75+
76+
$this->storeManager = $this->storeManager = $this->getMockForAbstractClass(
77+
\Magento\Store\Model\StoreManagerInterface::class,
78+
[],
79+
'',
80+
false
81+
);
82+
83+
$this->store = $this->getMockForAbstractClass(
84+
\Magento\Store\Api\Data\StoreInterface::class,
85+
[],
86+
'',
87+
false,
88+
false,
89+
true,
90+
['getWebsiteId', 'getRootCategoryId']
91+
);
92+
93+
$this->coreRegistry = $this->createMock(\Magento\Framework\Registry::class);
94+
95+
$objectManager = new ObjectManagerHelper($this);
96+
97+
$this->eavAttributeResource = $this->createPartialMock(
98+
\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class,
99+
[
100+
'__wakeup',
101+
'getBackendType',
102+
'getFrontendInput'
103+
]
104+
);
105+
106+
$this->mapper = $objectManager->getObject(
107+
\Magento\Elasticsearch\Model\Adapter\FieldMapper\ProductFieldMapper::class,
108+
[
109+
'eavConfig' => $this->eavConfig,
110+
'storeManager' => $this->storeManager,
111+
'fieldType' => $this->fieldType,
112+
'customerSession' => $this->customerSession,
113+
'coreRegistry' => $this->coreRegistry
114+
]
115+
);
116+
}
117+
118+
/**
119+
* @dataProvider attributeCodeProvider
120+
* @param string $attributeCode
121+
* @param string $fieldName
122+
* @param string $fieldType
123+
* @param array $context
124+
*
125+
* @return void
126+
*/
127+
public function testGetFieldName($attributeCode, $fieldName, $fieldType, $context = [])
128+
{
129+
$attributeMock = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class)
130+
->setMethods(['getBackendType', 'getFrontendInput', 'getAttribute'])
131+
->disableOriginalConstructor()
132+
->getMock();
133+
134+
$this->customerSession->expects($this->any())
135+
->method('getCustomerGroupId')
136+
->willReturn('0');
137+
138+
$this->storeManager->expects($this->any())
139+
->method('getStore')
140+
->willReturn($this->store);
141+
$this->store->expects($this->any())
142+
->method('getWebsiteId')
143+
->willReturn('1');
144+
$this->store->expects($this->any())
145+
->method('getRootCategoryId')
146+
->willReturn('1');
147+
148+
$this->eavConfig->expects($this->any())->method('getAttribute')
149+
->with(ProductAttributeInterface::ENTITY_TYPE_CODE, $attributeCode)
150+
->willReturn($attributeMock);
151+
152+
$attributeMock->expects($this->any())->method('getFrontendInput')
153+
->will($this->returnValue('select'));
154+
155+
$this->fieldType->expects($this->any())->method('getFieldType')
156+
->with($attributeMock)
157+
->willReturn($fieldType);
158+
159+
$this->assertEquals(
160+
$fieldName,
161+
$this->mapper->getFieldName($attributeCode, $context)
162+
);
163+
}
164+
165+
/**
166+
* @return void
167+
*/
168+
public function testGetFieldNameWithoutAttribute()
169+
{
170+
$this->eavConfig->expects($this->any())->method('getAttribute')
171+
->with(ProductAttributeInterface::ENTITY_TYPE_CODE, 'attr1')
172+
->willReturn('');
173+
174+
$this->assertEquals(
175+
'attr1',
176+
$this->mapper->getFieldName('attr1', [])
177+
);
178+
}
179+
180+
/**
181+
* @dataProvider attributeProvider
182+
* @param string $attributeCode
183+
*
184+
* @return void
185+
*/
186+
public function testGetAllAttributesTypes($attributeCode, $inputType, $searchAttributes, $expected)
187+
{
188+
$attributeMock = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class)
189+
->disableOriginalConstructor()
190+
->getMock();
191+
192+
$this->eavConfig->expects($this->any())->method('getEntityAttributeCodes')
193+
->with(ProductAttributeInterface::ENTITY_TYPE_CODE)
194+
->willReturn([$attributeCode]);
195+
196+
$this->eavConfig->expects($this->any())->method('getAttribute')
197+
->with(ProductAttributeInterface::ENTITY_TYPE_CODE, $attributeCode)
198+
->willReturn($attributeMock);
199+
200+
$this->fieldType->expects($this->once())->method('getFieldType')->willReturn(FieldType::ES_DATA_TYPE_INT);
201+
202+
$attributeMock->expects($this->any())
203+
->method('getIsSearchable')
204+
->willReturn($searchAttributes['searchable']);
205+
$attributeMock->expects($this->any())
206+
->method('getIsFilterable')
207+
->willReturn($searchAttributes['filterable']);
208+
$attributeMock->expects($this->any())
209+
->method('getIsFilterableInSearch')
210+
->willReturn($searchAttributes['filterableInSearch']);
211+
$attributeMock->expects($this->any())
212+
->method('getIsVisibleInAdvancedSearch')
213+
->willReturn($searchAttributes['advSearch']);
214+
215+
$attributeMock->expects($this->any())->method('getFrontendInput')
216+
->will($this->returnValue($inputType));
217+
218+
$this->assertEquals(
219+
$expected,
220+
$this->mapper->getAllAttributesTypes()
221+
);
222+
}
223+
224+
/**
225+
* @return array
226+
*/
227+
public function attributeCodeProvider()
228+
{
229+
return [
230+
['id', 'id', 'string'],
231+
['status', 'status', 'string'],
232+
['status', 'status_value', 'string', ['type'=>'default']],
233+
['price', 'price_0_1', 'string', ['type'=>'default']],
234+
['position', 'position_category_1', 'string', ['type'=>'default']],
235+
['price', 'price_2_3', 'string', ['type'=>'default', 'customerGroupId'=>'2', 'websiteId'=>'3']],
236+
['position', 'position_category_3', 'string', ['type'=>'default', 'categoryId'=>'3']],
237+
['color', 'color_value', 'string', ['type'=>'text']],
238+
['description', 'sort_description', 'string', ['type'=>'some']],
239+
['*', '_all', 'string', ['type'=>'text']],
240+
['description', 'description_value', 'string', ['type'=>'text']],
241+
];
242+
}
243+
244+
/**
245+
* @return array
246+
*/
247+
public function attributeProvider()
248+
{
249+
return [
250+
[
251+
'category_ids',
252+
'text',
253+
['searchable' => false, 'filterable' => false, 'filterableInSearch' => false, 'advSearch' => false],
254+
['category_ids' => ['type' => 'integer']]
255+
],
256+
[
257+
'attr_code',
258+
'string',
259+
['searchable' => false, 'filterable' => false, 'filterableInSearch' => false, 'advSearch' => false],
260+
['attr_code' => ['type' => 'integer', 'index' => 'no']]
261+
],
262+
[
263+
'attr_code',
264+
'string',
265+
['searchable' => '0', 'filterable' => '0', 'filterableInSearch' => '0', 'advSearch' => '0'],
266+
['attr_code' => ['type' => 'integer', 'index' => 'no']]
267+
],
268+
[
269+
'attr_code',
270+
'string',
271+
['searchable' => true, 'filterable' => false, 'filterableInSearch' => false, 'advSearch' => false],
272+
['attr_code' => ['type' => 'integer']]
273+
],
274+
[
275+
'attr_code',
276+
'string',
277+
['searchable' => '1', 'filterable' => '0', 'filterableInSearch' => '0', 'advSearch' => '0'],
278+
['attr_code' => ['type' => 'integer']]
279+
],
280+
[
281+
'attr_code',
282+
'string',
283+
['searchable' => false, 'filterable' => false, 'filterableInSearch' => false, 'advSearch' => true],
284+
['attr_code' => ['type' => 'integer']]
285+
],
286+
[
287+
'attr_code',
288+
'string',
289+
['searchable' => '0', 'filterable' => '0', 'filterableInSearch' => '1', 'advSearch' => '0'],
290+
['attr_code' => ['type' => 'integer']]
291+
],
292+
];
293+
}
294+
}

0 commit comments

Comments
 (0)