@@ -59,9 +59,396 @@ Next step is to configure your first entity. This entity is for e-shop product.
5959
6060---
6161
62- ## 3.
62+ ## 3. Create entity class
6363
64+ ` ` ` php
65+ <?php declare(strict_types = 1);
66+
67+ class SimpleProduct implements \Spameri\Elastic\Entity\IElasticEntity
68+ {
69+
70+ public function __construct(
71+ \Spameri\Elastic\Entity\Property\IElasticId $id,
72+ int $databaseId,
73+ string $name,
74+ ?string $content,
75+ string $alias,
76+ string $image,
77+ float $price,
78+ string $availability,
79+ array $tags,
80+ array $categories
81+ )
82+ {
83+ // ...
84+ }
85+
86+ }
87+ ```
88+
89+ ``` php
90+ public function id(): \Spameri\Elastic\Entity\Property\IElasticId
91+ {
92+ return $this->id;
93+ }
94+
95+
96+ public function entityVariables(): array
97+ {
98+ return \get_object_vars($this);
99+ }
100+ ```
101+
102+ ### Factory
103+ ```` php
104+ class SimpleProductFactory implements \Spameri\Elastic\Factory\IEntityFactory
105+ {
106+
107+ public function create(\Spameri\ElasticQuery\Response\Result\Hit $hit) : \Generator
108+ {
109+ yield new \App\ProductModule\Entity\SimpleProduct(
110+ new \Spameri\Elastic\Entity\Property\ElasticId($hit->id()),
111+ $hit->getValue('databaseId'),
112+ $hit->getValue('name'),
113+ $hit->getValue('content'),
114+ $hit->getValue('alias'),
115+ $hit->getValue('image'),
116+ $hit->getValue('price'),
117+ $hit->getValue('availability'),
118+ $hit->getValue('tags'),
119+ $hit->getValue('categories')
120+ );
121+ }
122+
123+ }
124+ ````
125+
126+ ### CollectionFactory
127+ ```` php
128+ class SimpleProductCollectionFactory implements \Spameri\Elastic\Factory\ICollectionFactory
129+ {
130+
131+ public function create(
132+ \Spameri\Elastic\Model\IService $service
133+ , array $elasticIds = []
134+ , \Spameri\Elastic\Entity\IElasticEntity ... $entityCollection
135+ ) : \Spameri\Elastic\Entity\IElasticEntityCollection
136+ {
137+ return new \App\ProductModule\Entity\ProductCollection($service, $elasticIds, ... $entityCollection);
138+ }
139+
140+ }
141+ ````
142+
143+ ## 4. Index Configuring
144+ ```` php
145+ class SimpleProductConfig implements \Spameri\Elastic\Settings\IndexConfigInterface
146+ {
147+ public function __construct(
148+ string $indexName
149+ )
150+ {
151+ $this->indexName = $indexName;
152+ }
153+ }
154+ ````
155+
156+ ` public function provide(): \Spameri\ElasticQuery\Mapping\Settings `
157+
158+ ```` php
159+ $settings = new \Spameri\ElasticQuery\Mapping\Settings($this->indexName);
160+ $czechDictionary = new \Spameri\ElasticQuery\Mapping\Analyzer\Custom\CzechDictionary();
161+ $settings->addAnalyzer($czechDictionary);
162+
163+ $lowerCase = new \Spameri\ElasticQuery\Mapping\Analyzer\Custom\Lowercase();
164+ $settings->addAnalyzer($lowerCase);
165+ ````
166+
167+ ```` php
168+ $settings->addMappingField(
169+ new \Spameri\ElasticQuery\Mapping\Settings\Mapping\Field(
170+ 'databaseId',
171+ \Spameri\Elastic\Model\ValidateMapping\AllowedValues::TYPE_KEYWORD
172+ )
173+ );
174+ $settings->addMappingField(
175+ new \Spameri\ElasticQuery\Mapping\Settings\Mapping\Field(
176+ 'name',
177+ \Spameri\Elastic\Model\ValidateMapping\AllowedValues::TYPE_TEXT,
178+ $czechDictionary
179+ )
180+ );
181+ $settings->addMappingField(
182+ new \Spameri\ElasticQuery\Mapping\Settings\Mapping\Field(
183+ 'content',
184+ \Spameri\Elastic\Model\ValidateMapping\AllowedValues::TYPE_TEXT,
185+ $czechDictionary
186+ )
187+ );
188+ ````
189+
190+
191+ ```` php
192+ $settings->addMappingField(
193+ new \Spameri\ElasticQuery\Mapping\Settings\Mapping\Field(
194+ 'tags',
195+ \Spameri\Elastic\Model\ValidateMapping\AllowedValues::TYPE_TEXT,
196+ $lowerCase
197+ )
198+ );
199+ ````
200+
201+
202+ ## 5. Export data to ElasticSearch
203+
204+ ```` php
205+ class ExportToElastic extends \Spameri\Elastic\Import\Run
206+ {
207+
208+ public function __construct(
209+ string $logDir = 'log',
210+ \Symfony\Component\Console\Output\ConsoleOutput $output,
211+ \Spameri\Elastic\Import\Run\NullLoggerHandler $loggerHandler,
212+ \Spameri\Elastic\Import\Lock\NullLock $lock,
213+ \Spameri\Elastic\Import\RunHandler\NullHandler $runHandler,
214+
215+ \App\ProductModule\Model\ExportToElastic\DataProvider $dataProvider,
216+ \App\ProductModule\Model\ExportToElastic\PrepareImportData $prepareImportData,
217+ \App\ProductModule\Model\ExportToElastic\DataImport $dataImport,
218+
219+ \Spameri\Elastic\Import\AfterImport\NullAfterImport $afterImport
220+ )
221+ {
222+ parent::__construct($logDir, $output, $loggerHandler, $lock, $runHandler, $dataProvider, $prepareImportData, $dataImport, $afterImport);
223+ }
224+
225+ }
226+ ````
227+
228+
229+ ```` php
230+ class DataProvider implements \Spameri\Elastic\Import\DataProviderInterface
231+ {
232+ public function provide(\Spameri\Elastic\Import\Run\Options $options): \Generator
233+ {
234+ $query = $this->connection->select('*')->from('table');
235+
236+ while ($hasResults) {
237+ $items = $query->fetchAll($offset, $limit);
238+
239+ yield from $items;
240+
241+ if ( ! \count($items)) {
242+ $hasResults = FALSE;
243+
244+ } else {
245+ $offset += $limit;
246+ }
247+ }
248+ }
249+ }
250+ ````
64251
65252
253+ ```` php
254+
255+ class PrepareImportData implements \Spameri\Elastic\Import\PrepareImportDataInterface
256+ {
257+
258+ public function prepare($entityData): \Spameri\Elastic\Entity\AbstractImport
259+ {
260+ $imageSrc = '//via.placeholder.com/150x150';
261+ $elasticId = NULL;
262+ $tags = [];
263+ $categories = [];
264+ return new \App\ProductModule\Entity\SimpleProduct(
265+ $elasticId,
266+ $entityData['id'],
267+ $entityData['name'],
268+ $entityData['content_description'],
269+ $entityData['alias'],
270+ $imageSrc,
271+ $entityData['amount'],
272+ $entityData['availability_id'] === 1 ? 'Skladem' : 'Nedostupné',
273+ $tags,
274+ $categories
275+ );
276+ }
277+
278+ }
279+ ````
280+
281+ ```` php
282+ class DataImport implements \Spameri\Elastic\Import\DataImportInterface
283+ {
284+
285+ /**
286+ * @param \App\ProductModule\Entity\SimpleProduct $entity
287+ */
288+ public function import(
289+ \Spameri\Elastic\Entity\AbstractImport $entity
290+ ): \Spameri\Elastic\Import\ResponseInterface
291+ {
292+ $id = $this->productService->insert($entity);
293+
294+ return new \Spameri\Elastic\Import\Response\SimpleResponse(
295+ $id,
296+ $entity
297+ );
298+ }
299+
300+ }
301+ ````
302+
303+ ```` php
304+ $options = new \Spameri\Elastic\Import\Run\Options(600);
305+
306+ // Clear index
307+ try {
308+ $this->delete->execute($this->simpleProductConfig->provide()->indexName());
309+ } catch (\Spameri\Elastic\Exception\ElasticSearchException $exception) {}
310+
311+ // Create index
312+ $this->create->execute(
313+ $this->simpleProductConfig->provide()->indexName(),
314+ $this->simpleProductConfig->provide()->toArray()
315+ );
316+
317+ // Export
318+ $this->exportToElastic->execute($options);
319+ ````
320+
321+ ## 6. Presenter, Form, Template
322+ ```` php
323+ class SimpleProductListPresenter extends \App\Presenter\BasePresenter
324+ {
325+
326+ public function renderDefault($queryString): void
327+ {
328+ $query = $this->buildQuery($queryString);
329+
330+ try {
331+ $products = $this->productService->getAllBy($query);
332+
333+ } catch (\Spameri\Elastic\Exception\ElasticSearchException $exception) {
334+ $products = [];
335+ }
336+
337+ $this->getTemplate()->add(
338+ 'products',
339+ $products
340+ );
341+ $this->getTemplate()->add(
342+ 'queryString',
343+ $queryString
344+ );
345+ }
346+
347+ }
348+ ````
349+
350+ ```` php
351+ public function createComponentSearchForm() :\Nette\Application\UI\Form
352+ {
353+ $form = new \Nette\Application\UI\Form();
354+ $form->addText('queryString', 'query')
355+ ->setAttribute('class', 'inp-text suggest')
356+ ;
357+
358+ $form->addSubmit('search', 'Search');
359+
360+ $form->onSuccess[] = function () use ($form) {
361+ $this->redirect(
362+ 301,
363+ ':Product:SimpleProductList:default',
364+ [
365+ 'queryString' => $form->getValues()->queryString,
366+ ]
367+ );
368+ };
369+
370+ return $form;
371+ }
372+ ````
373+
374+ ```` php
375+ {control searchForm}
376+ <h2 >You have searched: {$queryString}</h2 >
377+
378+ <div class =" product-list products-list-full" >
379+ <ul class =" reset products full-products" >
380+ {foreach $products as $product}
381+ <li >
382+ <div class =" spc" >
383+ <a href =" //benu.cz/{$product->getAlias()}" class =" detail" style =" height : 321px " >
384+ <h2 class =" title" >
385+ <span class =" img" >
386+ <img class =" lazy lazy-loaded" src =" {$product->getImage()}" width =" 180" height =" 156" alt =" {$product->getName()}" >
387+ </span >
388+ <span class =" name" style =" height : 48px ;" >{$product->getName()|truncate:40}</span >
389+ </h2 >
390+ ````
391+
392+ ## 7. Search
393+
394+ ``` php
395+ public function buildQuery(?string $queryString): \Spameri\ElasticQuery\ElasticQuery
396+ {
397+ $query = new \Spameri\ElasticQuery\ElasticQuery();
398+ $query->addShouldQuery(
399+ new \Spameri\ElasticQuery\Query\Match(
400+ 'name',
401+ $queryString
402+ )
403+ );
404+
405+ return $query;
406+ }
407+ ```
408+
409+ ```` php
410+ $products = $this->productService->getAllBy($query);
411+ ````
412+
413+ ## 8. Fine Tuning
414+
415+ ```` php
416+ $subQuery = new \Spameri\ElasticQuery\Query\QueryCollection();
417+ ````
418+
419+ ``` php
420+ $subQuery->addShouldQuery(
421+ new \Spameri\ElasticQuery\Query\Match(
422+ 'name',
423+ $queryString,
424+ 3,
425+ \Spameri\ElasticQuery\Query\Match\Operator::OR,
426+ new \Spameri\ElasticQuery\Query\Match\Fuzziness(\Spameri\ElasticQuery\Query\Match\Fuzziness::AUTO)
427+ )
428+ );
429+ $subQuery->addShouldQuery(
430+ new \Spameri\ElasticQuery\Query\WildCard(
431+ 'name',
432+ $queryString . '*',
433+ 1
434+ )
435+ );
436+ $subQuery->addShouldQuery(
437+ new \Spameri\ElasticQuery\Query\MatchPhrase(
438+ 'name',
439+ $queryString,
440+ 1
441+ )
442+ );
443+ $subQuery->addShouldQuery(
444+ new \Spameri\ElasticQuery\Query\Match(
445+ 'content',
446+ $queryString,
447+ 1,
448+ \Spameri\ElasticQuery\Query\Match\Operator:: OR,
449+ new \Spameri\ElasticQuery\Query\Match\Fuzziness(\Spameri\ElasticQuery\Query\Match\Fuzziness::AUTO)
450+ )
451+ );
452+ ```
66453
67454
0 commit comments