Completed
Push — master ( f3ba17...48df0d )
by Simonas
29:24 queued 19:17
created

src/Search.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/*
4
 * This file is part of the ONGR package.
5
 *
6
 * (c) NFQ Technologies UAB <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace ONGR\ElasticsearchDSL;
13
14
use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
15
use ONGR\ElasticsearchDSL\Highlight\Highlight;
16
use ONGR\ElasticsearchDSL\InnerHit\NestedInnerHit;
17
use ONGR\ElasticsearchDSL\Query\BoolQuery;
18
use ONGR\ElasticsearchDSL\SearchEndpoint\AbstractSearchEndpoint;
19
use ONGR\ElasticsearchDSL\SearchEndpoint\AggregationsEndpoint;
20
use ONGR\ElasticsearchDSL\SearchEndpoint\FilterEndpoint;
21
use ONGR\ElasticsearchDSL\SearchEndpoint\HighlightEndpoint;
22
use ONGR\ElasticsearchDSL\SearchEndpoint\InnerHitsEndpoint;
23
use ONGR\ElasticsearchDSL\SearchEndpoint\PostFilterEndpoint;
24
use ONGR\ElasticsearchDSL\SearchEndpoint\QueryEndpoint;
25
use ONGR\ElasticsearchDSL\SearchEndpoint\SearchEndpointFactory;
26
use ONGR\ElasticsearchDSL\SearchEndpoint\SearchEndpointInterface;
27
use ONGR\ElasticsearchDSL\SearchEndpoint\SortEndpoint;
28
use ONGR\ElasticsearchDSL\Serializer\Normalizer\CustomReferencedNormalizer;
29
use ONGR\ElasticsearchDSL\Serializer\OrderedSerializer;
30
use Symfony\Component\Serializer\Normalizer\CustomNormalizer;
31
use ONGR\ElasticsearchDSL\SearchEndpoint\SuggestEndpoint;
32
33
/**
34
 * Search object that can be executed by a manager.
35
 */
36
class Search
37
{
38
    /**
39
     * @var int
40
     */
41
    private $size;
42
43
    /**
44
     * @var int
45
     */
46
    private $from;
47
48
    /**
49
     * @var string
50
     */
51
    private $timeout;
52
53
    /**
54
     * @var int
55
     */
56
    private $terminateAfter;
57
58
    /**
59
     * @var string|null
60
     */
61
    private $scroll;
62
63
    /**
64
     * @var array|bool|string
65
     */
66
    private $source;
67
68
    /**
69
     * @var array
70
     */
71
    private $storedFields;
72
73
    /**
74
     * @var array
75
     */
76
    private $scriptFields;
77
78
    /**
79
     * @var string
80
     */
81
    private $searchType;
82
83
    /**
84
     * @var string
85
     */
86
    private $requestCache;
87
88
    /**
89
     * @var bool
90
     */
91
    private $explain;
92
93
    /**
94
     * @var array
95
     */
96
    private $stats;
97
98
    /**
99
     * @var string[]
100
     */
101
    private $preference;
102
103
    /**
104
     * @var float
105
     */
106
    private $minScore;
107
108
    /**
109
     * @var OrderedSerializer
110
     */
111
    private $serializer;
112
113
    /**
114
     * @var SearchEndpointInterface[]
115
     */
116
    private $endpoints = [];
117
118
    /**
119
     * Initializes serializer.
120
     */
121
    public function __construct()
122
    {
123
        $this->serializer = new OrderedSerializer(
124
            [
125
                new CustomReferencedNormalizer(),
126
                new CustomNormalizer(),
127
            ]
128
        );
129
    }
130
131
    /**
132
     * Returns endpoint instance.
133
     *
134
     * @param string $type Endpoint type.
135
     *
136
     * @return SearchEndpointInterface
137
     */
138
    private function getEndpoint($type)
139
    {
140
        if (!array_key_exists($type, $this->endpoints)) {
141
            $this->endpoints[$type] = SearchEndpointFactory::get($type);
142
        }
143
144
        return $this->endpoints[$type];
145
    }
146
147
    /**
148
     * Destroys search endpoint.
149
     *
150
     * @param string $type Endpoint type.
151
     */
152
    public function destroyEndpoint($type)
153
    {
154
        unset($this->endpoints[$type]);
155
    }
156
157
    /**
158
     * Sets parameters to the endpoint.
159
     *
160
     * @param string $endpointName
161
     * @param array  $parameters
162
     */
163
    private function setEndpointParameters($endpointName, array $parameters)
164
    {
165
        /** @var AbstractSearchEndpoint $endpoint */
166
        $endpoint = $this->getEndpoint($endpointName);
167
        $endpoint->setParameters($parameters);
168
    }
169
170
    /**
171
     * Adds query to the search.
172
     *
173
     * @param BuilderInterface $query
174
     * @param string           $boolType
175
     * @param string           $key
176
     *
177
     * @return $this
178
     */
179 View Code Duplication
    public function addQuery(BuilderInterface $query, $boolType = BoolQuery::MUST, $key = null)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
180
    {
181
        $endpoint = $this->getEndpoint(QueryEndpoint::NAME);
182
        $endpoint->addToBool($query, $boolType, $key);
183
184
        return $this;
185
    }
186
187
    /**
188
     * Returns queries inside BoolQuery instance.
189
     *
190
     * @return BuilderInterface
191
     */
192
    public function getQueries()
193
    {
194
        $endpoint = $this->getEndpoint(QueryEndpoint::NAME);
195
196
        return $endpoint->getBool();
197
    }
198
199
    /**
200
     * Sets query endpoint parameters.
201
     *
202
     * @param array $parameters
203
     *
204
     * @return $this
205
     */
206
    public function setQueryParameters(array $parameters)
207
    {
208
        $this->setEndpointParameters(QueryEndpoint::NAME, $parameters);
209
210
        return $this;
211
    }
212
213
    /**
214
     * Adds a filter to the search.
215
     *
216
     * @param BuilderInterface $filter   Filter.
217
     * @param string           $boolType Example boolType values:
218
     *                                   - must
219
     *                                   - must_not
220
     *                                   - should.
221
     * @param string           $key
222
     *
223
     * @return $this
224
     */
225 View Code Duplication
    public function addFilter(BuilderInterface $filter, $boolType = BoolQuery::MUST, $key = null)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
226
    {
227
        // Trigger creation of QueryEndpoint as filters depends on it
228
        $this->getEndpoint(QueryEndpoint::NAME);
229
230
        $endpoint = $this->getEndpoint(FilterEndpoint::NAME);
231
        $endpoint->addToBool($filter, $boolType, $key);
0 ignored issues
show
$boolType is of type string, but the function expects a array|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
It seems like $key defined by parameter $key on line 225 can also be of type string; however, ONGR\ElasticsearchDSL\Se...tInterface::addToBool() does only seem to accept array|null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
232
233
        return $this;
234
    }
235
236
    /**
237
     * Returns queries inside BoolFilter instance.
238
     *
239
     * @return BuilderInterface
240
     */
241
    public function getFilters()
242
    {
243
        $endpoint = $this->getEndpoint(FilterEndpoint::NAME);
244
245
        return $endpoint->getBool();
246
    }
247
248
    /**
249
     * Sets filter endpoint parameters.
250
     *
251
     * @param array $parameters
252
     *
253
     * @return $this
254
     */
255
    public function setFilterParameters(array $parameters)
256
    {
257
        $this->setEndpointParameters(FilterEndpoint::NAME, $parameters);
258
259
        return $this;
260
    }
261
262
    /**
263
     * Adds a post filter to search.
264
     *
265
     * @param BuilderInterface $filter   Filter.
266
     * @param string           $boolType Example boolType values:
267
     *                                   - must
268
     *                                   - must_not
269
     *                                   - should.
270
     * @param string           $key
271
     *
272
     * @return int Key of post filter.
273
     */
274
    public function addPostFilter(BuilderInterface $filter, $boolType = BoolQuery::MUST, $key = null)
275
    {
276
        $this
277
            ->getEndpoint(PostFilterEndpoint::NAME)
278
            ->addToBool($filter, $boolType, $key);
279
280
        return $this;
281
    }
282
283
    /**
284
     * Returns queries inside BoolFilter instance.
285
     *
286
     * @return BuilderInterface
287
     */
288
    public function getPostFilters()
289
    {
290
        $endpoint = $this->getEndpoint(PostFilterEndpoint::NAME);
291
292
        return $endpoint->getBool();
293
    }
294
295
    /**
296
     * Sets post filter endpoint parameters.
297
     *
298
     * @param array $parameters
299
     *
300
     * @return $this
301
     */
302
    public function setPostFilterParameters(array $parameters)
303
    {
304
        $this->setEndpointParameters(PostFilterEndpoint::NAME, $parameters);
305
306
        return $this;
307
    }
308
309
    /**
310
     * Adds aggregation into search.
311
     *
312
     * @param AbstractAggregation $aggregation
313
     *
314
     * @return $this
315
     */
316
    public function addAggregation(AbstractAggregation $aggregation)
317
    {
318
        $this->getEndpoint(AggregationsEndpoint::NAME)->add($aggregation, $aggregation->getName());
319
320
        return $this;
321
    }
322
323
    /**
324
     * Returns all aggregations.
325
     *
326
     * @return BuilderInterface[]
327
     */
328
    public function getAggregations()
329
    {
330
        return $this->getEndpoint(AggregationsEndpoint::NAME)->getAll();
331
    }
332
333
    /**
334
     * Adds inner hit into search.
335
     *
336
     * @param NestedInnerHit $innerHit
337
     *
338
     * @return $this
339
     */
340
    public function addInnerHit(NestedInnerHit $innerHit)
341
    {
342
        $this->getEndpoint(InnerHitsEndpoint::NAME)->add($innerHit, $innerHit->getName());
343
344
        return $this;
345
    }
346
347
    /**
348
     * Returns all inner hits.
349
     *
350
     * @return BuilderInterface[]
351
     */
352
    public function getInnerHits()
353
    {
354
        return $this->getEndpoint(InnerHitsEndpoint::NAME)->getAll();
355
    }
356
357
    /**
358
     * Adds sort to search.
359
     *
360
     * @param BuilderInterface $sort
361
     *
362
     * @return $this
363
     */
364
    public function addSort(BuilderInterface $sort)
365
    {
366
        $this->getEndpoint(SortEndpoint::NAME)->add($sort);
367
368
        return $this;
369
    }
370
371
    /**
372
     * Returns all set sorts.
373
     *
374
     * @return BuilderInterface[]
375
     */
376
    public function getSorts()
377
    {
378
        return $this->getEndpoint(SortEndpoint::NAME)->getAll();
379
    }
380
381
    /**
382
     * Allows to highlight search results on one or more fields.
383
     *
384
     * @param Highlight $highlight
385
     *
386
     * @return int Key of highlight.
387
     */
388
    public function addHighlight($highlight)
389
    {
390
        $this->getEndpoint(HighlightEndpoint::NAME)->add($highlight);
391
392
        return $this;
393
    }
394
395
    /**
396
     * Returns highlight builder.
397
     *
398
     * @return BuilderInterface
399
     */
400
    public function getHighlight()
401
    {
402
        /** @var HighlightEndpoint $highlightEndpoint */
403
        $highlightEndpoint = $this->getEndpoint(HighlightEndpoint::NAME);
404
405
        return $highlightEndpoint->getHighlight();
406
    }
407
408
    /**
409
    * Adds suggest into search.
410
    *
411
    * @param BuilderInterface $suggest
412
    *
413
    * @return $this
414
    */
415
    public function addSuggest(BuilderInterface $suggest)
416
    {
417
        $this->getEndpoint(SuggestEndpoint::NAME)->add($suggest, $suggest->getName());
418
419
        return $this;
420
    }
421
422
    /**
423
    * Returns all suggests.
424
    *
425
    * @return BuilderInterface[]
426
    */
427
    public function getSuggests()
428
    {
429
        return $this->getEndpoint(SuggestEndpoint::NAME)->getAll();
430
    }
431
432
    /**
433
     * Exclude documents which have a _score less than the minimum specified.
434
     *
435
     * @param float $minScore
436
     *
437
     * @return $this
438
     */
439
    public function setMinScore($minScore)
440
    {
441
        $this->minScore = $minScore;
442
443
        return $this;
444
    }
445
446
    /**
447
     * Returns min score value.
448
     *
449
     * @return float
450
     */
451
    public function getMinScore()
452
    {
453
        return $this->minScore;
454
    }
455
456
    /**
457
     * Paginate reed removed lts from.
458
     *
459
     * @param int $from
460
     *
461
     * @return $this
462
     */
463
    public function setFrom($from)
464
    {
465
        $this->from = $from;
466
467
        return $this;
468
    }
469
470
    /**
471
     * Sets timeout for query execution.
472
     *
473
     * @param string $timeout
474
     *
475
     * @return $this
476
     */
477
    public function setTimeout($timeout)
478
    {
479
        $this->timeout = $timeout;
480
481
        return $this;
482
    }
483
484
    /**
485
     * Sets maximum number of documents per shard.
486
     *
487
     * @param int $terminateAfter
488
     *
489
     * @return $this
490
     */
491
    public function setTerminateAfter($terminateAfter)
492
    {
493
        $this->terminateAfter = $terminateAfter;
494
495
        return $this;
496
    }
497
498
    /**
499
     * Returns results offset value.
500
     *
501
     * @return int
502
     */
503
    public function getFrom()
504
    {
505
        return $this->from;
506
    }
507
508
    /**
509
     * Set maximum number of results.
510
     *
511
     * @param int $size
512
     *
513
     * @return $this
514
     */
515
    public function setSize($size)
516
    {
517
        $this->size = $size;
518
519
        return $this;
520
    }
521
522
    /**
523
     * Returns maximum number of results query can request.
524
     *
525
     * @return int
526
     */
527
    public function getSize()
528
    {
529
        return $this->size;
530
    }
531
532
    /**
533
     * Allows to control how the _source field is returned with every hit.
534
     *
535
     * @param array|bool|string $source
536
     *
537
     * @return $this
538
     */
539
    public function setSource($source)
540
    {
541
        $this->source = $source;
542
543
        return $this;
544
    }
545
546
    /**
547
     * Returns source value.
548
     *
549
     * @return array|bool|string
550
     */
551
    public function getSource()
552
    {
553
        return $this->source;
554
    }
555
556
    /**
557
     * Allows to selectively load specific stored fields for each document represented by a search hit.
558
     *
559
     * @param array $storedFields
560
     *
561
     * @return $this
562
     */
563
    public function setStoredFields(array $storedFields)
564
    {
565
        $this->storedFields = $storedFields;
566
567
        return $this;
568
    }
569
570
    /**
571
     * Returns field value.
572
     *
573
     * @return array
574
     */
575
    public function getStoredFields()
576
    {
577
        return $this->storedFields;
578
    }
579
580
    /**
581
     * Allows to return a script evaluation (based on different fields) for each hit.
582
     *
583
     * @param array $scriptFields
584
     *
585
     * @return $this
586
     */
587
    public function setScriptFields($scriptFields)
588
    {
589
        $this->scriptFields = $scriptFields;
590
591
        return $this;
592
    }
593
594
    /**
595
     * Returns containing script fields.
596
     *
597
     * @return array
598
     */
599
    public function getScriptFields()
600
    {
601
        return $this->scriptFields;
602
    }
603
604
    /**
605
     * Sets explain property in request body search.
606
     *
607
     * @param bool $explain
608
     *
609
     * @return $this
610
     */
611
    public function setExplain($explain)
612
    {
613
        $this->explain = $explain;
614
615
        return $this;
616
    }
617
618
    /**
619
     * Returns if explain property is set in request body search.
620
     *
621
     * @return bool
622
     */
623
    public function isExplain()
624
    {
625
        return $this->explain;
626
    }
627
628
    /**
629
     * Sets a stats group.
630
     *
631
     * @param array $stats
632
     *
633
     * @return $this
634
     */
635
    public function setStats($stats)
636
    {
637
        $this->stats = $stats;
638
639
        return $this;
640
    }
641
642
    /**
643
     * Returns a stats group.
644
     *
645
     * @return array
646
     */
647
    public function getStats()
648
    {
649
        return $this->stats;
650
    }
651
652
    /**
653
     * Setter for scroll duration, effectively setting if search is scrolled or not.
654
     *
655
     * @param string|null $duration
656
     *
657
     * @return $this
658
     */
659
    public function setScroll($duration = '5m')
660
    {
661
        $this->scroll = $duration;
662
663
        return $this;
664
    }
665
666
    /**
667
     * Returns scroll duration.
668
     *
669
     * @return string|null
670
     */
671
    public function getScroll()
672
    {
673
        return $this->scroll;
674
    }
675
676
    /**
677
     * Set search type.
678
     *
679
     * @param string $searchType
680
     *
681
     * @return $this
682
     */
683
    public function setSearchType($searchType)
684
    {
685
        $this->searchType = $searchType;
686
687
        return $this;
688
    }
689
690
    /**
691
     * Returns search type used.
692
     *
693
     * @return string
694
     */
695
    public function getSearchType()
696
    {
697
        return $this->searchType;
698
    }
699
700
701
    /**
702
     * Set request cache.
703
     *
704
     * @param string $requestCache
705
     *
706
     * @return $this
707
     */
708
    public function setRequestCache($requestCache)
709
    {
710
        $this->requestCache = $requestCache;
711
712
        return $this;
713
    }
714
715
    /**
716
     * Returns request cache.
717
     *
718
     * @return string
719
     */
720
    public function getRequestCache()
721
    {
722
        return $this->requestCache;
723
    }
724
725
    /**
726
     * Setter for preference.
727
     *
728
     * Controls which shard replicas to execute the search request on.
729
     *
730
     * @param mixed $preferenceParams Example values:
731
     *                                _primary
732
     *                                _primary_first
733
     *                                _local
734
     *                                _only_node:xyz (xyz - node id)
735
     *                                _prefer_node:xyz (xyz - node id)
736
     *                                _shards:2,3 (2 and 3 specified shards)
737
     *                                custom value
738
     *                                string[] combination of params.
739
     *
740
     * @return $this
741
     */
742
    public function setPreference($preferenceParams)
743
    {
744
        if (is_string($preferenceParams)) {
745
            $this->preference[] = $preferenceParams;
746
        }
747
748
        if (is_array($preferenceParams) && !empty($preferenceParams)) {
749
            $this->preference = $preferenceParams;
750
        }
751
752
        return $this;
753
    }
754
755
    /**
756
     * Returns preference params as string.
757
     *
758
     * @return string
759
     */
760
    public function getPreference()
761
    {
762
        return $this->preference ? implode(';', $this->preference) : null;
763
    }
764
765
    /**
766
     * Returns query url parameters.
767
     *
768
     * @return array
769
     */
770
    public function getQueryParams()
771
    {
772
        return array_filter(
773
            [
774
                'scroll' => $this->getScroll(),
775
                'search_type' => $this->getSearchType(),
776
                'request_cache' => $this->getRequestCache(),
777
                'preference' => $this->getPreference(),
778
            ]
779
        );
780
    }
781
782
    /**
783
     * {@inheritdoc}
784
     */
785
    public function toArray()
786
    {
787
        $output = array_filter($this->serializer->normalize($this->endpoints));
788
789
        $params = [
790
            'from' => 'from',
791
            'size' => 'size',
792
            'storedFields' => 'stored_fields',
793
            'scriptFields' => 'script_fields',
794
            'explain' => 'explain',
795
            'stats' => 'stats',
796
            'minScore' => 'min_score',
797
            'source' => '_source',
798
            'timeout' => 'timeout',
799
            'terminateAfter' => 'terminate_after',
800
        ];
801
802
        foreach ($params as $field => $param) {
803
            if ($this->$field !== null) {
804
                $output[$param] = $this->$field;
805
            }
806
        }
807
808
        return $output;
809
    }
810
}
811