Completed
Push — master ( 61efdf...7a2c62 )
by Simonas
01:38
created

src/Search.php (1 issue)

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\Compound\BoolQuery;
18
use ONGR\ElasticsearchDSL\SearchEndpoint\AbstractSearchEndpoint;
19
use ONGR\ElasticsearchDSL\SearchEndpoint\AggregationsEndpoint;
20
use ONGR\ElasticsearchDSL\SearchEndpoint\HighlightEndpoint;
21
use ONGR\ElasticsearchDSL\SearchEndpoint\InnerHitsEndpoint;
22
use ONGR\ElasticsearchDSL\SearchEndpoint\PostFilterEndpoint;
23
use ONGR\ElasticsearchDSL\SearchEndpoint\QueryEndpoint;
24
use ONGR\ElasticsearchDSL\SearchEndpoint\SearchEndpointFactory;
25
use ONGR\ElasticsearchDSL\SearchEndpoint\SearchEndpointInterface;
26
use ONGR\ElasticsearchDSL\SearchEndpoint\SortEndpoint;
27
use ONGR\ElasticsearchDSL\Serializer\Normalizer\CustomReferencedNormalizer;
28
use ONGR\ElasticsearchDSL\Serializer\OrderedSerializer;
29
use Symfony\Component\Serializer\Normalizer\CustomNormalizer;
30
use ONGR\ElasticsearchDSL\SearchEndpoint\SuggestEndpoint;
31
32
/**
33
 * Search object that can be executed by a manager.
34
 */
35
class Search
36
{
37
    /**
38
     * To retrieve hits from a certain offset. Defaults to 0.
39
     *
40
     * @var int
41
     */
42
    private $from;
43
44
    /**
45
     * The number of hits to return. Defaults to 10. If you do not care about getting some
46
     * hits back but only about the number of matches and/or aggregations, setting the value
47
     * to 0 will help performance.
48
     *
49
     * @var int
50
     */
51
    private $size;
52
53
    /**
54
     * Allows to control how the _source field is returned with every hit. By default
55
     * operations return the contents of the _source field unless you have used the
56
     * stored_fields parameter or if the _source field is disabled.
57
     *
58
     * @var bool
59
     */
60
    private $source;
61
62
    /**
63
     * Allows to selectively load specific stored fields for each document represented by a search hit.
64
     *
65
     * @var array
66
     */
67
    private $storedFields;
68
69
    /**
70
     * Allows to return a script evaluation (based on different fields) for each hit.
71
     * Script fields can work on fields that are not stored, and allow to return custom
72
     * values to be returned (the evaluated value of the script). Script fields can
73
     * also access the actual _source document indexed and extract specific elements
74
     * to be returned from it (can be an "object" type).
75
     *
76
     * @var array
77
     */
78
    private $scriptFields;
79
80
    /**
81
     * Allows to return the doc value representation of a field for each hit. Doc value
82
     * fields can work on fields that are not stored. Note that if the fields parameter
83
     * specifies fields without docvalues it will try to load the value from the fielddata
84
     * cache causing the terms for that field to be loaded to memory (cached), which will
85
     * result in more memory consumption.
86
     *
87
     * @var array
88
     */
89
    private $docValueFields;
90
91
    /**
92
     * Enables explanation for each hit on how its score was computed.
93
     *
94
     * @var bool
95
     */
96
    private $explain;
97
98
    /**
99
     * Returns a version for each search hit.
100
     *
101
     * @var bool
102
     */
103
    private $version;
104
105
    /**
106
     * Allows to configure different boost level per index when searching across more
107
     * than one indices. This is very handy when hits coming from one index matter more
108
     * than hits coming from another index (think social graph where each user has an index).
109
     *
110
     * @var array
111
     */
112
    private $indicesBoost;
113
114
    /**
115
     * Exclude documents which have a _score less than the minimum specified in min_score.
116
     *
117
     * @var int
118
     */
119
    private $minScore;
120
121
    /**
122
     * Pagination of results can be done by using the from and size but the cost becomes
123
     * prohibitive when the deep pagination is reached. The index.max_result_window which
124
     * defaults to 10,000 is a safeguard, search requests take heap memory and time
125
     * proportional to from + size. The Scroll api is recommended for efficient deep
126
     * scrolling but scroll contexts are costly and it is not recommended to use it for
127
     * real time user requests. The search_after parameter circumvents this problem by
128
     * providing a live cursor. The idea is to use the results from the previous page to
129
     * help the retrieval of the next page.
130
     *
131
     * @var array
132
     */
133
    private $searchAfter;
134
135
    /**
136
     * URI parameters alongside Request body search.
137
     *
138
     * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-uri-request.html
139
     *
140
     * @var array
141
     */
142
    private $uriParams = [];
143
144
    /**
145
     * While a search request returns a single “page” of results, the scroll API can be used to retrieve
146
     * large numbers of results (or even all results) from a single search request, in much the same way
147
     * as you would use a cursor on a traditional database. Scrolling is not intended for real time user
148
     * requests, but rather for processing large amounts of data, e.g. in order to reindex the contents
149
     * of one index into a new index with a different configuration.
150
     *
151
     * @var string
152
     */
153
    private $scroll;
154
155
    /**
156
     * @var OrderedSerializer
157
     */
158
    private static $serializer;
159
160
    /**
161
     * @var SearchEndpointInterface[]
162
     */
163
    private $endpoints = [];
164
165
    /**
166
     * Initializes serializer.
167
     */
168
    public function __construct()
169
    {
170
        if (static::$serializer === null) {
171
            static::$serializer = new OrderedSerializer(
172
                [
173
                    new CustomReferencedNormalizer(),
174
                    new CustomNormalizer(),
175
                ]
176
            );
177
        }
178
    }
179
180
    /**
181
     * Destroys search endpoint.
182
     *
183
     * @param string $type Endpoint type.
184
     */
185
    public function destroyEndpoint($type)
186
    {
187
        unset($this->endpoints[$type]);
188
    }
189
190
    /**
191
     * Adds query to the search.
192
     *
193
     * @param BuilderInterface $query
194
     * @param string           $boolType
195
     * @param string           $key
196
     *
197
     * @return $this
198
     */
199
    public function addQuery(BuilderInterface $query, $boolType = BoolQuery::MUST, $key = null)
200
    {
201
        $endpoint = $this->getEndpoint(QueryEndpoint::NAME);
202
        $endpoint->addToBool($query, $boolType, $key);
203
204
        return $this;
205
    }
206
207
    /**
208
     * Returns endpoint instance.
209
     *
210
     * @param string $type Endpoint type.
211
     *
212
     * @return SearchEndpointInterface
213
     */
214
    private function getEndpoint($type)
215
    {
216
        if (!array_key_exists($type, $this->endpoints)) {
217
            $this->endpoints[$type] = SearchEndpointFactory::get($type);
218
        }
219
220
        return $this->endpoints[$type];
221
    }
222
223
    /**
224
     * Returns queries inside BoolQuery instance.
225
     *
226
     * @return BuilderInterface
227
     */
228
    public function getQueries()
229
    {
230
        $endpoint = $this->getEndpoint(QueryEndpoint::NAME);
231
232
        return $endpoint->getBool();
233
    }
234
235
    /**
236
     * Sets query endpoint parameters.
237
     *
238
     * @param array $parameters
239
     *
240
     * @return $this
241
     */
242
    public function setQueryParameters(array $parameters)
243
    {
244
        $this->setEndpointParameters(QueryEndpoint::NAME, $parameters);
245
246
        return $this;
247
    }
248
249
    /**
250
     * Sets parameters to the endpoint.
251
     *
252
     * @param string $endpointName
253
     * @param array  $parameters
254
     */
255
    public function setEndpointParameters($endpointName, array $parameters)
256
    {
257
        /** @var AbstractSearchEndpoint $endpoint */
258
        $endpoint = $this->getEndpoint($endpointName);
259
        $endpoint->setParameters($parameters);
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 $this.
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 $this.
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 getHighlights()
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(NamedBuilderInterface $suggest)
416
    {
417
        $this->getEndpoint(SuggestEndpoint::NAME)->add($suggest, $suggest->getName());
0 ignored issues
show
$suggest->getName() 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...
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
     * @return int
434
     */
435
    public function getFrom()
436
    {
437
        return $this->from;
438
    }
439
440
    /**
441
     * @param int $from
442
     * @return $this
443
     */
444
    public function setFrom($from)
445
    {
446
        $this->from = $from;
447
        return $this;
448
    }
449
450
    /**
451
     * @return int
452
     */
453
    public function getSize()
454
    {
455
        return $this->size;
456
    }
457
458
    /**
459
     * @param int $size
460
     * @return $this
461
     */
462
    public function setSize($size)
463
    {
464
        $this->size = $size;
465
        return $this;
466
    }
467
468
    /**
469
     * @return bool
470
     */
471
    public function isSource()
472
    {
473
        return $this->source;
474
    }
475
476
    /**
477
     * @param bool $source
478
     * @return $this
479
     */
480
    public function setSource($source)
481
    {
482
        $this->source = $source;
483
        return $this;
484
    }
485
486
    /**
487
     * @return array
488
     */
489
    public function getStoredFields()
490
    {
491
        return $this->storedFields;
492
    }
493
494
    /**
495
     * @param array $storedFields
496
     * @return $this
497
     */
498
    public function setStoredFields($storedFields)
499
    {
500
        $this->storedFields = $storedFields;
501
        return $this;
502
    }
503
504
    /**
505
     * @return array
506
     */
507
    public function getScriptFields()
508
    {
509
        return $this->scriptFields;
510
    }
511
512
    /**
513
     * @param array $scriptFields
514
     * @return $this
515
     */
516
    public function setScriptFields($scriptFields)
517
    {
518
        $this->scriptFields = $scriptFields;
519
        return $this;
520
    }
521
522
    /**
523
     * @return array
524
     */
525
    public function getDocValueFields()
526
    {
527
        return $this->docValueFields;
528
    }
529
530
    /**
531
     * @param array $docValueFields
532
     * @return $this
533
     */
534
    public function setDocValueFields($docValueFields)
535
    {
536
        $this->docValueFields = $docValueFields;
537
        return $this;
538
    }
539
540
    /**
541
     * @return bool
542
     */
543
    public function isExplain()
544
    {
545
        return $this->explain;
546
    }
547
548
    /**
549
     * @param bool $explain
550
     * @return $this
551
     */
552
    public function setExplain($explain)
553
    {
554
        $this->explain = $explain;
555
        return $this;
556
    }
557
558
    /**
559
     * @return bool
560
     */
561
    public function isVersion()
562
    {
563
        return $this->version;
564
    }
565
566
    /**
567
     * @param bool $version
568
     * @return $this
569
     */
570
    public function setVersion($version)
571
    {
572
        $this->version = $version;
573
        return $this;
574
    }
575
576
    /**
577
     * @return array
578
     */
579
    public function getIndicesBoost()
580
    {
581
        return $this->indicesBoost;
582
    }
583
584
    /**
585
     * @param array $indicesBoost
586
     * @return $this
587
     */
588
    public function setIndicesBoost($indicesBoost)
589
    {
590
        $this->indicesBoost = $indicesBoost;
591
        return $this;
592
    }
593
594
    /**
595
     * @return int
596
     */
597
    public function getMinScore()
598
    {
599
        return $this->minScore;
600
    }
601
602
    /**
603
     * @param int $minScore
604
     * @return $this
605
     */
606
    public function setMinScore($minScore)
607
    {
608
        $this->minScore = $minScore;
609
        return $this;
610
    }
611
612
    /**
613
     * @return array
614
     */
615
    public function getSearchAfter()
616
    {
617
        return $this->searchAfter;
618
    }
619
620
    /**
621
     * @param array $searchAfter
622
     * @return $this
623
     */
624
    public function setSearchAfter($searchAfter)
625
    {
626
        $this->searchAfter = $searchAfter;
627
        return $this;
628
    }
629
630
    /**
631
     * @return string
632
     */
633
    public function getScroll()
634
    {
635
        return $this->scroll;
636
    }
637
638
    /**
639
     * @param string $scroll
640
     * @return $this
641
     */
642
    public function setScroll($scroll = '5m')
643
    {
644
        $this->scroll = $scroll;
645
646
        $this->addUriParam('scroll', $this->scroll);
647
648
        return $this;
649
    }
650
651
    /**
652
     * @param string $name
653
     * @param string|array|bool $value
654
     *
655
     * @return $this
656
     */
657
    public function addUriParam($name, $value)
658
    {
659
        if (in_array($name, [
660
            'q',
661
            'df',
662
            'analyzer',
663
            'analyze_wildcard',
664
            'default_operator',
665
            'lenient',
666
            'explain',
667
            '_source',
668
            '_source_exclude',
669
            '_source_include',
670
            'stored_fields',
671
            'sort',
672
            'track_scores',
673
            'timeout',
674
            'terminate_after',
675
            'from',
676
            'size',
677
            'search_type',
678
            'scroll',
679
            'allow_no_indices',
680
            'ignore_unavailable',
681
            'typed_keys',
682
            'pre_filter_shard_size',
683
            'ignore_unavailable',
684
        ])) {
685
            $this->uriParams[$name] = $value;
686
        } else {
687
            throw new \InvalidArgumentException(sprintf('Parameter %s is not supported.', $value));
688
        }
689
690
        return $this;
691
    }
692
693
    /**
694
     * Returns query url parameters.
695
     *
696
     * @return array
697
     */
698
    public function getUriParams()
699
    {
700
        return $this->uriParams;
701
    }
702
703
    /**
704
     * {@inheritdoc}
705
     */
706
    public function toArray()
707
    {
708
        $output = array_filter(static::$serializer->normalize($this->endpoints));
709
710
        $params = [
711
            'from' => 'from',
712
            'size' => 'size',
713
            'source' => '_source',
714
            'storedFields' => 'stored_fields',
715
            'scriptFields' => 'script_fields',
716
            'docValueFields' => 'docvalue_fields',
717
            'explain' => 'explain',
718
            'version' => 'version',
719
            'indicesBoost' => 'indices_boost',
720
            'minScore' => 'min_score',
721
            'searchAfter' => 'search_after',
722
        ];
723
724
        foreach ($params as $field => $param) {
725
            if ($this->$field !== null) {
726
                $output[$param] = $this->$field;
727
            }
728
        }
729
730
        return $output;
731
    }
732
}
733