Skip to content

Commit eab031f

Browse files
author
Oleksandr Gorkun
committed
MAGETWO-83426: [Performance] Customer Import check data does not complete
1 parent 46bdda9 commit eab031f

File tree

2 files changed

+113
-111
lines changed

2 files changed

+113
-111
lines changed

app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Address/Storage.php

Lines changed: 48 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
*/
66
namespace Magento\CustomerImportExport\Model\ResourceModel\Import\Address;
77

8-
use Magento\Customer\Api\AddressRepositoryInterface;
9-
use Magento\Framework\Api\FilterBuilder;
10-
use Magento\Framework\Api\SearchCriteriaBuilder;
8+
use Magento\Customer\Model\ResourceModel\Address\CollectionFactory as AddressCollectionFactory;
9+
use Magento\Framework\DataObject;
10+
use Magento\Framework\DB\Select;
11+
use Magento\ImportExport\Model\ResourceModel\CollectionByPagesIterator as CollectionIterator;
12+
use Magento\Customer\Model\ResourceModel\Address\Collection as AddressCollection;
1113

1214
/**
1315
* Storage to check existing addresses.
@@ -22,33 +24,27 @@ class Storage
2224
private $addresses = [];
2325

2426
/**
25-
* @var AddressRepositoryInterface
27+
* @var AddressCollectionFactory
2628
*/
27-
private $addressRepository;
29+
private $addressCollectionFactory;
2830

2931
/**
30-
* @var SearchCriteriaBuilder
31-
*/
32-
private $searchCriteriaBuilder;
33-
34-
/**
35-
* @var FilterBuilder
32+
* For iterating over large number of addresses.
33+
*
34+
* @var CollectionIterator
3635
*/
37-
private $filterBuilder;
36+
protected $collectionIterator;
3837

3938
/**
40-
* @param AddressRepositoryInterface $addressRepository
41-
* @param SearchCriteriaBuilder $searchCriteriaBuilder
42-
* @param FilterBuilder $filterBuilder
39+
* @param AddressCollectionFactory $addressCollectionFactory
40+
* @param CollectionIterator $byPagesIterator
4341
*/
4442
public function __construct(
45-
AddressRepositoryInterface $addressRepository,
46-
SearchCriteriaBuilder $searchCriteriaBuilder,
47-
FilterBuilder $filterBuilder
43+
AddressCollectionFactory $addressCollectionFactory,
44+
CollectionIterator $byPagesIterator
4845
) {
49-
$this->addressRepository = $addressRepository;
50-
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
51-
$this->filterBuilder = $filterBuilder;
46+
$this->addressCollectionFactory = $addressCollectionFactory;
47+
$this->collectionIterator = $byPagesIterator;
5248
}
5349

5450
/**
@@ -75,6 +71,33 @@ private function addRecord($customerId, $addressId)
7571
}
7672
}
7773

74+
/**
75+
* Load addresses IDs for given customers.
76+
*
77+
* @param string[] $customerIds
78+
*
79+
* @return void
80+
*/
81+
private function loadAddresses(array $customerIds)
82+
{
83+
/** @var AddressCollection $collection */
84+
$collection = $this->addressCollectionFactory->create();
85+
$collection->removeAttributeToSelect();
86+
$select = $collection->getSelect();
87+
$tableId = array_keys($select->getPart(Select::FROM))[0];
88+
$select->where($tableId .'.parent_id in (?)', $customerIds);
89+
90+
$this->collectionIterator->iterate(
91+
$collection,
92+
5000,
93+
[
94+
function (DataObject $record) {
95+
$this->addRecord($record->getParentId(), $record->getId());
96+
}
97+
]
98+
);
99+
}
100+
78101
/**
79102
* Check if given address exists for given customer.
80103
*
@@ -104,24 +127,14 @@ public function prepareAddresses(array $forCustomersIds)
104127
return;
105128
}
106129

107-
$filters = [];
130+
$forCustomersIds = array_unique($forCustomersIds);
131+
$customerIdsToUse = [];
108132
foreach ($forCustomersIds as $customerId) {
109133
if (!array_key_exists((string)$customerId, $this->addresses)) {
110-
$filters[] = $this->filterBuilder
111-
->setField('parent_id')
112-
->setValue($customerId)
113-
->setConditionType('eq')
114-
->create();
134+
$customerIdsToUse[] = $customerId;
115135
}
116136
}
117-
$this->searchCriteriaBuilder->addFilters($filters);
118137

119-
//Adding addresses that we found.
120-
$found = $this->addressRepository->getList(
121-
$this->searchCriteriaBuilder->create()
122-
);
123-
foreach ($found->getItems() as $address) {
124-
$this->addRecord($address->getCustomerId(), $address->getId());
125-
}
138+
$this->loadAddresses($customerIdsToUse);
126139
}
127140
}

app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Customer/Storage.php

Lines changed: 65 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@
55
*/
66
namespace Magento\CustomerImportExport\Model\ResourceModel\Import\Customer;
77

8-
use Magento\Customer\Api\CustomerRepositoryInterface;
9-
use Magento\Framework\Api\SearchCriteriaBuilder;
10-
use Magento\Framework\App\ObjectManager;
118
use Magento\Framework\DataObject;
12-
use Magento\Framework\Exception\NoSuchEntityException;
13-
use Magento\Framework\Api\FilterBuilder;
9+
use Magento\Framework\DB\Select;
10+
use Magento\Customer\Model\ResourceModel\Customer\CollectionFactory as CustomerCollectionFactory;
11+
use Magento\Customer\Model\ResourceModel\Customer\Collection as CustomerCollection;
1412

1513
class Storage
1614
{
@@ -25,7 +23,7 @@ class Storage
2523
/**
2624
* Customer collection
2725
*
28-
* @var \Magento\Customer\Model\ResourceModel\Customer\Collection
26+
* @var CustomerCollection
2927
* @deprecated
3028
*/
3129
protected $_customerCollection;
@@ -48,48 +46,30 @@ class Storage
4846
* Number of items to fetch from db in one query
4947
*
5048
* @var int
51-
* @deprecated
5249
*/
5350
protected $_pageSize;
5451

5552
/**
5653
* Collection by pages iterator
5754
*
5855
* @var \Magento\ImportExport\Model\ResourceModel\CollectionByPagesIterator
59-
* @deprecated
6056
*/
6157
protected $_byPagesIterator;
6258

6359
/**
64-
* @var CustomerRepositoryInterface
65-
*/
66-
private $customerRepository;
67-
68-
/**
69-
* @var SearchCriteriaBuilder
70-
*/
71-
private $searchCriteriaBuilder;
72-
73-
/**
74-
* @var FilterBuilder
60+
* @var CustomerCollectionFactory
7561
*/
76-
private $filterBuilder;
62+
private $customerCollectionFactory;
7763

7864
/**
79-
* @param \Magento\Customer\Model\ResourceModel\Customer\CollectionFactory $collectionFactory
65+
* @param CustomerCollectionFactory $collectionFactory
8066
* @param \Magento\ImportExport\Model\ResourceModel\CollectionByPagesIteratorFactory $colIteratorFactory
8167
* @param array $data
82-
* @param CustomerRepositoryInterface|null $customerRepository
83-
* @param SearchCriteriaBuilder|null $searchCriteriaBuilder
84-
* @param FilterBuilder|null $filterBuilder
8568
*/
8669
public function __construct(
87-
\Magento\Customer\Model\ResourceModel\Customer\CollectionFactory $collectionFactory,
70+
CustomerCollectionFactory $collectionFactory,
8871
\Magento\ImportExport\Model\ResourceModel\CollectionByPagesIteratorFactory $colIteratorFactory,
89-
array $data = [],
90-
CustomerRepositoryInterface $customerRepository = null,
91-
SearchCriteriaBuilder $searchCriteriaBuilder = null,
92-
FilterBuilder $filterBuilder = null
72+
array $data = []
9373
) {
9474
$this->_customerCollection = isset(
9575
$data['customer_collection']
@@ -98,13 +78,7 @@ public function __construct(
9878
$this->_byPagesIterator = isset(
9979
$data['collection_by_pages_iterator']
10080
) ? $data['collection_by_pages_iterator'] : $colIteratorFactory->create();
101-
$this->customerRepository = $customerRepository
102-
?: ObjectManager::getInstance()
103-
->get(CustomerRepositoryInterface::class);
104-
$this->searchCriteriaBuilder = $searchCriteriaBuilder
105-
?: ObjectManager::getInstance()->get(SearchCriteriaBuilder::class);
106-
$this->filterBuilder = $filterBuilder
107-
?: ObjectManager::getInstance()->get(FilterBuilder::class);
81+
$this->customerCollectionFactory = $collectionFactory;
10882
}
10983

11084
/**
@@ -131,6 +105,49 @@ public function load()
131105
}
132106
}
133107

108+
/**
109+
* Create new collection to load customer data with proper filters.
110+
*
111+
* @param array[] $customerIdentifiers With keys "email" and "website_id".
112+
*
113+
* @return CustomerCollection
114+
*/
115+
private function prepareCollection(array $customerIdentifiers)
116+
{
117+
/** @var CustomerCollection $collection */
118+
$collection = $this->customerCollectionFactory->create();
119+
$collection->removeAttributeToSelect();
120+
$select = $collection->getSelect();
121+
$customerTableId = array_keys($select->getPart(Select::FROM))[0];
122+
$select->where(
123+
$customerTableId .'.email in (?)',
124+
array_map(
125+
function (array $customer) {
126+
return $customer['email'];
127+
},
128+
$customerIdentifiers
129+
)
130+
);
131+
132+
return $collection;
133+
}
134+
135+
/**
136+
* Load customers' data that can be found by given identifiers.
137+
*
138+
* @param array $customerIdentifiers With keys "email" and "website_id".
139+
*
140+
* @return void
141+
*/
142+
private function loadCustomersData(array $customerIdentifiers)
143+
{
144+
$this->_byPagesIterator->iterate(
145+
$this->prepareCollection($customerIdentifiers),
146+
$this->_pageSize,
147+
[[$this, 'addCustomer']]
148+
);
149+
}
150+
134151
/**
135152
* Add customer to array
136153
*
@@ -163,21 +180,9 @@ public function getCustomerId($email, $websiteId)
163180
if (!array_key_exists($email, $this->_customerIds)
164181
|| !array_key_exists($websiteId, $this->_customerIds[$email])
165182
) {
166-
try {
167-
$customer = $this->customerRepository->get($email, $websiteId);
168-
$customerData = new DataObject([
169-
'id' => $customer->getId(),
170-
'email' => $customer->getEmail(),
171-
'website_id' => $customer->getWebsiteId()
172-
]);
173-
} catch (NoSuchEntityException $exception) {
174-
$customerData = new DataObject([
175-
'id' => null,
176-
'email' => $email,
177-
'website_id' => $websiteId
178-
]);
179-
}
180-
$this->addCustomer($customerData);
183+
$this->loadCustomersData([
184+
['email' => $email, 'website_id' => $websiteId]
185+
]);
181186
}
182187

183188
if (isset($this->_customerIds[$email][$websiteId])) {
@@ -195,47 +200,31 @@ public function getCustomerId($email, $websiteId)
195200
*/
196201
public function prepareCustomers(array $customersToFind)
197202
{
198-
$customersData = [];
199-
$filters = [];
203+
$identifiers = [];
200204
foreach ($customersToFind as $customerToFind) {
201205
$email = mb_strtolower($customerToFind['email']);
202206
$websiteId = $customerToFind['website_id'];
203207
if (!array_key_exists($email, $this->_customerIds)
204208
|| !array_key_exists($websiteId, $this->_customerIds[$email])
205209
) {
206210
//Only looking for customers we don't already have ID for.
207-
$customersData[] = [
211+
$uniqueKey = $email .'_' .$websiteId;
212+
$identifiers[$uniqueKey] = [
208213
'email' => $email,
209214
'website_id' => $websiteId
210215
];
211-
$filters[] = $this->filterBuilder
212-
->setField('email')
213-
->setValue($email)
214-
->setConditionType('eq')
215-
->create();
216216
}
217217
}
218-
if (!$customersData) {
218+
if (!$identifiers) {
219219
return;
220220
}
221+
//Loading customers data.
222+
$this->loadCustomersData($identifiers);
221223

222-
$this->searchCriteriaBuilder->addFilters($filters);
223-
224-
//Adding customers that we found.
225-
$found = $this->customerRepository->getList(
226-
$this->searchCriteriaBuilder->create()
227-
);
228-
foreach ($found->getItems() as $customer) {
229-
$this->addCustomer(new DataObject([
230-
'id' => $customer->getId(),
231-
'email' => $customer->getEmail(),
232-
'website_id' => $customer->getWebsiteId()
233-
]));
234-
}
235224
//Adding customers that don't exist.
236-
foreach ($customersData as $customerData) {
237-
$email = $customerData['email'];
238-
$websiteId = $customerData['website_id'];
225+
foreach ($identifiers as $customerIdentity) {
226+
$email = $customerIdentity['email'];
227+
$websiteId = $customerIdentity['website_id'];
239228
if (!array_key_exists($email, $this->_customerIds)
240229
|| !array_key_exists($websiteId, $this->_customerIds[$email])
241230
) {

0 commit comments

Comments
 (0)