Skip to content

Commit 2e4beb0

Browse files
MAGETWO-90564: [Indexer optimizations] Catalog Rule indexer matching mechanism optimization
1 parent f5debf0 commit 2e4beb0

File tree

26 files changed

+4121
-9
lines changed

26 files changed

+4121
-9
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
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\Catalog\Model\Api\SearchCriteria\CollectionProcessor\ConditionProcessor\ConditionBuilder;
9+
10+
use Magento\Framework\Api\SearchCriteria\CollectionProcessor\ConditionProcessor\CustomConditionInterface;
11+
use Magento\Framework\Api\Filter;
12+
use Magento\Catalog\Model\ResourceModel\Product\Collection;
13+
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
14+
15+
/**
16+
* Based on Magento\Framework\Api\Filter builds condition
17+
* that can be applied to Catalog\Model\ResourceModel\Product\Collection
18+
* to filter products that has specific value for EAV attribute
19+
*/
20+
class EavAttributeCondition implements CustomConditionInterface
21+
{
22+
/**
23+
* @var \Magento\Framework\App\ResourceConnection
24+
*/
25+
private $resourceConnection;
26+
27+
/**
28+
* @var \Magento\Eav\Model\Config
29+
*/
30+
private $eavConfig;
31+
32+
/**
33+
* @param \Magento\Eav\Model\Config $eavConfig
34+
* @param \Magento\Framework\App\ResourceConnection $resourceConnection
35+
*/
36+
public function __construct(
37+
\Magento\Eav\Model\Config $eavConfig,
38+
\Magento\Framework\App\ResourceConnection $resourceConnection
39+
) {
40+
$this->eavConfig = $eavConfig;
41+
$this->resourceConnection = $resourceConnection;
42+
}
43+
44+
/**
45+
* @param Filter $filter
46+
* @return string
47+
* @throws \DomainException
48+
* @throws \Magento\Framework\Exception\LocalizedException
49+
*/
50+
public function build(Filter $filter): string
51+
{
52+
$attribute = $this->getAttributeByCode($filter->getField());
53+
$tableAlias = 'ca_' . $attribute->getAttributeCode();
54+
55+
$conditionType = $this->mapConditionType($filter->getConditionType());
56+
$conditionValue = $this->mapConditionValue($conditionType, $filter->getValue());
57+
58+
// NOTE: store scope was ignored intentionally to perform search across all stores
59+
$attributeSelect = $this->resourceConnection->getConnection()
60+
->select()
61+
->from(
62+
[$tableAlias => $attribute->getBackendTable()],
63+
$tableAlias . '.' . $attribute->getEntityIdField()
64+
)->where(
65+
$this->resourceConnection->getConnection()->prepareSqlCondition(
66+
$tableAlias . '.' . $attribute->getIdFieldName(),
67+
['eq' => $attribute->getAttributeId()]
68+
)
69+
)->where(
70+
$this->resourceConnection->getConnection()->prepareSqlCondition(
71+
$tableAlias . '.value',
72+
[$conditionType => $conditionValue]
73+
)
74+
);
75+
76+
return $this->resourceConnection
77+
->getConnection()
78+
->prepareSqlCondition(
79+
Collection::MAIN_TABLE_ALIAS . '.' . $attribute->getEntityIdField(),
80+
[
81+
'in' => $attributeSelect
82+
]
83+
);
84+
}
85+
86+
/**
87+
* @param string $field
88+
* @return Attribute
89+
* @throws \Magento\Framework\Exception\LocalizedException
90+
*/
91+
private function getAttributeByCode(string $field): Attribute
92+
{
93+
return $this->eavConfig->getAttribute(\Magento\Catalog\Model\Product::ENTITY, $field);
94+
}
95+
96+
/**
97+
* Map equal and not equal conditions to in and not in
98+
*
99+
* @param string $conditionType
100+
* @return mixed
101+
*/
102+
private function mapConditionType(string $conditionType): string
103+
{
104+
$conditionsMap = [
105+
'eq' => 'in',
106+
'neq' => 'nin'
107+
];
108+
109+
return isset($conditionsMap[$conditionType]) ? $conditionsMap[$conditionType] : $conditionType;
110+
}
111+
112+
/**
113+
* Wraps value with '%' if condition type is 'like' or 'not like'
114+
*
115+
* @param string $conditionType
116+
* @param string $conditionValue
117+
* @return string
118+
*/
119+
private function mapConditionValue(string $conditionType, string $conditionValue): string
120+
{
121+
$conditionsMap = ['like', 'nlike'];
122+
123+
if (in_array($conditionType, $conditionsMap)) {
124+
$conditionValue = '%' . $conditionValue . '%';
125+
}
126+
127+
return $conditionValue;
128+
}
129+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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\Catalog\Model\Api\SearchCriteria\CollectionProcessor\ConditionProcessor\ConditionBuilder;
9+
10+
use Magento\Framework\Api\Filter;
11+
use Magento\Framework\Api\SearchCriteria\CollectionProcessor\ConditionProcessor\CustomConditionInterface;
12+
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
13+
14+
/**
15+
* Creates appropriate condition builder based on filter field
16+
* - native attribute condition builder if filter field is native attribute in product
17+
* - eav condition builder if filter field is eav attribute
18+
*/
19+
class Factory
20+
{
21+
/**
22+
* @var \Magento\Eav\Model\Config
23+
*/
24+
private $eavConfig;
25+
26+
/**
27+
* @var \Magento\Catalog\Model\ResourceModel\Product
28+
*/
29+
private $productResource;
30+
31+
/**
32+
* @var CustomConditionInterface
33+
*/
34+
private $eavAttributeConditionBuilder;
35+
36+
/**
37+
* @var CustomConditionInterface
38+
*/
39+
private $nativeAttributeConditionBuilder;
40+
41+
/**
42+
* @param \Magento\Eav\Model\Config $eavConfig
43+
* @param \Magento\Catalog\Model\ResourceModel\Product $productResource
44+
* @param CustomConditionInterface $eavAttributeConditionBuilder
45+
* @param CustomConditionInterface $nativeAttributeConditionBuilder
46+
*/
47+
public function __construct(
48+
\Magento\Eav\Model\Config $eavConfig,
49+
\Magento\Catalog\Model\ResourceModel\Product $productResource,
50+
CustomConditionInterface $eavAttributeConditionBuilder,
51+
CustomConditionInterface $nativeAttributeConditionBuilder
52+
) {
53+
$this->eavConfig = $eavConfig;
54+
$this->productResource = $productResource;
55+
$this->eavAttributeConditionBuilder = $eavAttributeConditionBuilder;
56+
$this->nativeAttributeConditionBuilder = $nativeAttributeConditionBuilder;
57+
}
58+
59+
/**
60+
* @param Filter $filter
61+
* @return CustomConditionInterface
62+
* @throws \Magento\Framework\Exception\LocalizedException
63+
*/
64+
public function createByFilter(Filter $filter): CustomConditionInterface
65+
{
66+
$attribute = $this->getAttributeByCode($filter->getField());
67+
68+
if ($attribute->getBackendTable() === $this->productResource->getEntityTable()) {
69+
return $this->nativeAttributeConditionBuilder;
70+
}
71+
72+
return $this->eavAttributeConditionBuilder;
73+
}
74+
75+
/**
76+
* @param string $field
77+
* @return \Magento\Catalog\Model\ResourceModel\Eav\Attribute
78+
* @throws \Magento\Framework\Exception\LocalizedException
79+
*/
80+
private function getAttributeByCode(string $field): Attribute
81+
{
82+
return $this->eavConfig->getAttribute(\Magento\Catalog\Model\Product::ENTITY, $field);
83+
}
84+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
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\Catalog\Model\Api\SearchCriteria\CollectionProcessor\ConditionProcessor\ConditionBuilder;
9+
10+
use Magento\Catalog\Api\Data\ProductInterface;
11+
use Magento\Framework\Api\SearchCriteria\CollectionProcessor\ConditionProcessor\CustomConditionInterface;
12+
use Magento\Framework\Api\Filter;
13+
use Magento\Catalog\Model\ResourceModel\Product\Collection;
14+
15+
/**
16+
* Based on Magento\Framework\Api\Filter builds condition
17+
* that can be applied to Catalog\Model\ResourceModel\Product\Collection
18+
* to filter products that has specific value for their native attribute
19+
*/
20+
class NativeAttributeCondition implements CustomConditionInterface
21+
{
22+
/**
23+
* @var \Magento\Framework\App\ResourceConnection
24+
*/
25+
private $resourceConnection;
26+
27+
/**
28+
* @param \Magento\Framework\App\ResourceConnection $resourceConnection
29+
*/
30+
public function __construct(
31+
\Magento\Framework\App\ResourceConnection $resourceConnection
32+
) {
33+
$this->resourceConnection = $resourceConnection;
34+
}
35+
36+
/**
37+
* @param Filter $filter
38+
* @return string
39+
* @throws \DomainException
40+
*/
41+
public function build(Filter $filter): string
42+
{
43+
$conditionType = $this->mapConditionType($filter->getConditionType(), $filter->getField());
44+
$conditionValue = $this->mapConditionValue($conditionType, $filter->getValue());
45+
46+
return $this->resourceConnection
47+
->getConnection()
48+
->prepareSqlCondition(
49+
Collection::MAIN_TABLE_ALIAS . '.' . $filter->getField(),
50+
[
51+
$conditionType => $conditionValue
52+
]
53+
);
54+
}
55+
56+
/**
57+
* Map equal and not equal conditions to in and not in
58+
*
59+
* @param string $conditionType
60+
* @param string $field
61+
* @return mixed
62+
*/
63+
private function mapConditionType(string $conditionType, string $field): string
64+
{
65+
if (strtolower($field) === ProductInterface::SKU) {
66+
$conditionsMap = [
67+
'eq' => 'like',
68+
'neq' => 'nlike'
69+
];
70+
} else {
71+
$conditionsMap = [
72+
'eq' => 'in',
73+
'neq' => 'nin'
74+
];
75+
}
76+
77+
return isset($conditionsMap[$conditionType]) ? $conditionsMap[$conditionType] : $conditionType;
78+
}
79+
80+
/**
81+
* Wraps value with '%' if condition type is 'like' or 'not like'
82+
*
83+
* @param string $conditionType
84+
* @param string $conditionValue
85+
* @return string
86+
*/
87+
private function mapConditionValue(string $conditionType, string $conditionValue): string
88+
{
89+
$conditionsMap = ['like', 'nlike'];
90+
91+
if (in_array($conditionType, $conditionsMap)) {
92+
$conditionValue = '%' . $conditionValue . '%';
93+
}
94+
95+
return $conditionValue;
96+
}
97+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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\Catalog\Model\Api\SearchCriteria\CollectionProcessor\ConditionProcessor;
9+
10+
use Magento\Framework\Api\SearchCriteria\CollectionProcessor\ConditionProcessor\CustomConditionInterface;
11+
use Magento\Framework\Api\Filter;
12+
use Magento\Catalog\Model\Api\SearchCriteria\CollectionProcessor\ConditionProcessor\ConditionBuilder\Factory;
13+
14+
/**
15+
* Default condition builder for Catalog\Model\ResourceModel\Product\Collection
16+
*/
17+
class DefaultCondition implements CustomConditionInterface
18+
{
19+
/**
20+
* @var Factory
21+
*/
22+
private $conditionBuilderFactory;
23+
24+
/**
25+
* @param Factory $conditionBuilderFactory
26+
*/
27+
public function __construct(
28+
Factory $conditionBuilderFactory
29+
) {
30+
$this->conditionBuilderFactory = $conditionBuilderFactory;
31+
}
32+
33+
/**
34+
* @param Filter $filter
35+
* @return string
36+
*/
37+
public function build(Filter $filter): string
38+
{
39+
$filterBuilder = $this->conditionBuilderFactory->createByFilter($filter);
40+
41+
return $filterBuilder->build($filter);
42+
}
43+
}

0 commit comments

Comments
 (0)