Completed
Push — master ( cbc962...e137d9 )
by Nicolas
35s
created

tests/SearchTest.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
namespace Elastica\Test;
4
5
use Elastica\Aggregation\Cardinality;
6
use Elastica\Client;
7
use Elastica\Document;
8
use Elastica\Exception\InvalidException;
9
use Elastica\Exception\ResponseException;
10
use Elastica\Query;
11
use Elastica\Query\FunctionScore;
12
use Elastica\Query\MatchAll;
13
use Elastica\Query\QueryString;
14
use Elastica\Request;
15
use Elastica\Response;
16
use Elastica\ResultSet;
17
use Elastica\Script\Script;
18
use Elastica\Search;
19
use Elastica\Suggest;
20
use Elastica\Test\Base as BaseTest;
21
22
/**
23
 * @internal
24
 */
25
class SearchTest extends BaseTest
26
{
27
    /**
28
     * @group unit
29
     */
30
    public function testConstruct(): void
31
    {
32
        $client = $this->_getClient();
33
        $search = new Search($client);
34
35
        $this->assertSame($client, $search->getClient());
36
    }
37
38
    /**
39
     * @group functional
40
     */
41
    public function testAddIndex(): void
42
    {
43
        $client = $this->_getClient();
44
        $search = new Search($client);
45
46
        $index1 = $this->_createIndex();
47
        $index2 = $this->_createIndex();
48
49
        $search->addIndex($index1);
50
        $indices = $search->getIndices();
51
52
        $this->assertCount(1, $indices);
53
54
        $search->addIndex($index2);
55
        $indices = $search->getIndices();
56
57
        $this->assertCount(2, $indices);
58
59
        $this->assertContains($index1->getName(), $indices);
60
        $this->assertContains($index2->getName(), $indices);
61
62
        // Add string
63
        $search->addIndex('test3');
64
        $indices = $search->getIndices();
65
66
        $this->assertCount(3, $indices);
67
        $this->assertContains('test3', $indices);
68
    }
69
70
    /**
71
     * @group unit
72
     */
73
    public function testAddIndices(): void
74
    {
75
        $client = $this->_getClient();
76
        $search = new Search($client);
77
78
        $indices = [];
79
        $indices[] = $client->getIndex('elastica_test1');
80
        $indices[] = $client->getIndex('elastica_test2');
81
82
        $search->addIndices($indices);
83
84
        $this->assertCount(2, $search->getIndices());
85
    }
86
87
    /**
88
     * @group unit
89
     */
90
    public function testAddIndexInvalid(): void
91
    {
92
        $this->expectException(InvalidException::class);
93
94
        $client = $this->_getClient();
95
        $search = new Search($client);
96
97
        $search->addIndex(new \stdClass());
98
    }
99
100
    /**
101
     * @group unit
102
     */
103
    public function testAddNumericIndex(): void
104
    {
105
        $client = $this->_getClient();
106
        $search = new Search($client);
107
108
        $search->addIndex(1);
109
110
        $this->assertContains('1', $search->getIndices(), 'Make sure it has been added and converted to string');
111
    }
112
113
    /**
114
     * @group functional
115
     */
116
    public function testGetPath(): void
117
    {
118
        $client = $this->_getClient();
119
        $search1 = new Search($client);
120
121
        $index1 = $this->_createIndex();
122
        $index2 = $this->_createIndex();
123
124
        // No index
125
        $this->assertEquals('/_search', $search1->getPath());
126
127
        // Single index
128
        $search1->addIndex($index1);
129
        $this->assertEquals($index1->getName().'/_search', $search1->getPath());
130
131
        // Multiple indices
132
        $search1->addIndex($index2);
133
        $this->assertEquals($index1->getName().','.$index2->getName().'/_search', $search1->getPath());
134
    }
135
136
    /**
137
     * @group functional
138
     */
139
    public function testSearchRequest(): void
140
    {
141
        $client = $this->_getClient();
142
        $search1 = new Search($client);
143
        $index1 = $this->_createIndex();
144
145
        $result = $search1->search([]);
146
        $this->assertFalse($result->getResponse()->hasError());
147
148
        $search1->addIndex($index1);
149
150
        $result = $search1->search([]);
151
        $this->assertFalse($result->getResponse()->hasError());
152
153
        $result = $search1->search([]);
154
        $this->assertFalse($result->getResponse()->hasError());
155
    }
156
157
    /**
158
     * @group functional
159
     */
160
    public function testSearchScrollRequest(): void
161
    {
162
        $client = $this->_getClient();
163
164
        $index = $this->_createIndex();
165
166
        $docs = [];
167
        for ($x = 1; $x <= 10; ++$x) {
168
            $docs[] = new Document($x, ['id' => $x, 'testscroll' => 'jbafford']);
169
        }
170
171
        $index->addDocuments($docs);
172
        $index->refresh();
173
174
        $search = new Search($client);
175
        $search->addIndex($index);
176
        $search->setOption('size', 0);
177
        $result = $search->search([], [
178
            Search::OPTION_SCROLL => '5m',
179
            Search::OPTION_SIZE => 5,
180
        ]);
181
        $this->assertFalse($result->getResponse()->hasError());
182
183
        $scrollId = $result->getResponse()->getScrollId();
184
        $this->assertNotEmpty($scrollId);
185
        $this->assertCount(5, $result->getResults());
186
187
        //There are 10 items, and we're scrolling with a size of 5
188
        //So we should get two results of 5 items, and then no items
189
        //We should also have sent the raw scroll_id as the HTTP request body
190
        $search = new Search($client);
191
        $result = $search->search([], [
192
            Search::OPTION_SCROLL => '5m',
193
            Search::OPTION_SCROLL_ID => $scrollId,
194
        ]);
195
        $this->assertFalse($result->getResponse()->hasError());
196
        $this->assertCount(5, $result->getResults());
197
        $this->assertArrayNotHasKey(Search::OPTION_SCROLL_ID, $search->getClient()->getLastRequest()->getQuery());
198
        $this->assertEquals([Search::OPTION_SCROLL_ID => $scrollId], $search->getClient()->getLastRequest()->getData());
199
200
        $result = $search->search([], [
201
            Search::OPTION_SCROLL => '5m',
202
            Search::OPTION_SCROLL_ID => $scrollId,
203
        ]);
204
        $this->assertFalse($result->getResponse()->hasError());
205
        $this->assertCount(0, $result->getResults());
206
        $this->assertArrayNotHasKey(Search::OPTION_SCROLL_ID, $search->getClient()->getLastRequest()->getQuery());
207
        $this->assertEquals([Search::OPTION_SCROLL_ID => $scrollId], $search->getClient()->getLastRequest()->getData());
208
    }
209
210
    /**
211
     * Default Limit tests for \Elastica\Search.
212
     *
213
     * @group functional
214
     */
215
    public function testLimitDefaultSearch(): void
216
    {
217
        $client = $this->_getClient();
218
        $search = new Search($client);
219
220
        $index = $client->getIndex('zero');
221
        $index->create(
222
            [
223
                'settings' => [
224
                    'index' => [
225
                        'number_of_shards' => 1,
226
                        'number_of_replicas' => 0,
227
                    ],
228
                ],
229
            ],
230
            [
231
                'recreate' => true,
232
            ]
233
        );
234
235
        $index->addDocuments([
236
            new Document(1, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
237
            new Document(2, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
238
            new Document(3, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
239
            new Document(4, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
240
            new Document(5, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
241
            new Document(6, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
242
            new Document(7, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
243
            new Document(8, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
244
            new Document(9, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
245
            new Document(10, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
246
            new Document(11, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
247
        ]);
248
        $index->refresh();
249
250
        $search->addIndex($index);
251
252
        // default limit results  (default limit is 10)
253
        $resultSet = $search->search('farrelley');
254
        $this->assertEquals(10, $resultSet->count());
255
256
        // limit = 1
257
        $resultSet = $search->search('farrelley', 1);
258
        $this->assertEquals(1, $resultSet->count());
259
    }
260
261
    /**
262
     * @group functional
263
     */
264
    public function testArrayConfigSearch(): void
265
    {
266
        $client = $this->_getClient();
267
        $search = new Search($client);
268
269
        $index = $client->getIndex('zero');
270
        $index->create(
271
            [
272
                'settings' => [
273
                    'index' => [
274
                        'number_of_shards' => 1,
275
                        'number_of_replicas' => 0,
276
                    ],
277
                ],
278
            ],
279
            [
280
                'recreate' => true,
281
            ]
282
        );
283
284
        $docs = [];
285
        for ($i = 0; $i < 11; ++$i) {
286
            $docs[] = new Document($i, ['id' => 1, 'email' => '[email protected]', 'username' => 'test']);
287
        }
288
289
        $index->addDocuments($docs);
290
        $index->refresh();
291
292
        $search->addIndex($index);
293
        //Backward compatibility, integer => limit
294
        // default limit results  (default limit is 10)
295
        $resultSet = $search->search('test');
296
        $this->assertEquals(10, $resultSet->count());
297
298
        // limit = 1
299
        $resultSet = $search->search('test', 1);
300
        $this->assertEquals(1, $resultSet->count());
301
302
        //Array with limit
303
        $resultSet = $search->search('test', ['limit' => 2]);
304
        $this->assertEquals(2, $resultSet->count());
305
306
        //Array with size
307
        $resultSet = $search->search('test', ['size' => 2]);
308
        $this->assertEquals(2, $resultSet->count());
309
310
        //Array with from
311
        $resultSet = $search->search('test', ['from' => 10]);
312
        $this->assertEquals(10, $resultSet->current()->getId());
313
314
        //Array with routing
315
        $resultSet = $search->search('test', ['routing' => 'r1,r2']);
316
        $this->assertEquals(10, $resultSet->count());
317
318
        //Array with limit and routing
319
        $resultSet = $search->search('test', ['limit' => 5, 'routing' => 'r1,r2']);
320
        $this->assertEquals(5, $resultSet->count());
321
322
        //Array with terminate_after
323
        $resultSet = $search->search('test', ['terminate_after' => 100]);
324
        $this->assertEquals(10, $resultSet->count());
325
326
        $resultSet = $search->search('test', ['limit' => 0]);
327
        $this->assertTrue((0 === $resultSet->count()) && 11 === $resultSet->getTotalHits());
328
329
        //test with filter_path
330
        $resultSet = $search->search('test', [Search::OPTION_FILTER_PATH => 'hits.hits._source']);
331
        $filteredData = $resultSet->getResponse()->getData();
332
        $this->assertArrayNotHasKey('took', $filteredData);
333
        $this->assertArrayNotHasKey('max_score', $filteredData['hits']);
334
335
        //test with typed_keys
336
        $countIds = (new Cardinality('count_ids'))->setField('id');
337
        $suggestName = new Suggest((new Suggest\Term('name_suggest', 'username'))->setText('tes'));
338
        $typedKeysQuery = (new Query())
339
            ->addAggregation($countIds)
340
            ->setSuggest($suggestName)
341
        ;
342
        $resultSet = $search->search($typedKeysQuery, [Search::OPTION_TYPED_KEYS => true]);
343
        $this->assertNotEmpty($resultSet->getAggregation('cardinality#count_ids'));
344
        $this->assertNotEmpty($resultSet->getSuggests(), 'term#name_suggest');
345
346
        //Timeout - this one is a bit more tricky to test
347
        $mockResponse = new Response(\json_encode(['timed_out' => true]));
348
        $client = $this->createMock(Client::class);
349
        $client->method('request')
350
            ->willReturn($mockResponse)
351
        ;
352
        $search = new Search($client);
353
        $script = new Script('Thread.sleep(100); return _score;');
354
        $query = new FunctionScore();
355
        $query->addScriptScoreFunction($script);
356
        $resultSet = $search->search($query, ['timeout' => 50]);
357
        $this->assertTrue($resultSet->hasTimedOut());
358
    }
359
360
    /**
361
     * @group functional
362
     */
363
    public function testInvalidConfigSearch(): void
364
    {
365
        $this->expectException(InvalidException::class);
366
367
        $client = $this->_getClient();
368
        $search = new Search($client);
369
        $search->search('test', ['invalid_option' => 'invalid_option_value']);
370
    }
371
372
    /**
373
     * @group functional
374
     */
375 View Code Duplication
    public function testSearchWithVersionOption(): void
376
    {
377
        $index = $this->_createIndex();
378
        $doc = new Document(1, ['id' => 1, 'email' => '[email protected]', 'username' => 'ruflin']);
379
        $index->addDocuments([$doc]);
380
        $index->refresh();
381
382
        $search = new Search($index->getClient());
383
        $search->addIndex($index);
384
385
        // Version param should not be inside by default
386
        $results = $search->search(new MatchAll());
387
        $hit = $results->current();
388
        $this->assertEquals([], $hit->getParam('_version'));
389
390
        // Added version param to result
391
        $results = $search->search(new MatchAll(), ['version' => true]);
392
        $hit = $results->current();
393
        $this->assertEquals(1, $hit->getParam('_version'));
394
    }
395
396
    /**
397
     * @group functional
398
     */
399
    public function testSearchGet(): void
400
    {
401
        $client = $this->_getClient();
402
        $search1 = new Search($client);
403
404
        $result = $search1->search([], [], 'GET');
405
        $this->assertFalse($result->getResponse()->hasError());
406
    }
407
408
    /**
409
     * @group functional
410
     */
411
    public function testCountRequest(): void
412
    {
413
        $client = $this->_getClient();
414
        $search = new Search($client);
415
416
        $index = $client->getIndex('zero');
417
        $index->create(
418
            [
419
                'settings' => [
420
                    'index' => [
421
                        'number_of_shards' => 1,
422
                        'number_of_replicas' => 0,
423
                    ],
424
                ],
425
            ],
426
            [
427
                'recreate' => true,
428
            ]
429
        );
430
431
        $index->addDocuments([
432
            new Document(1, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
433
            new Document(2, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
434
            new Document(3, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
435
            new Document(4, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
436
            new Document(5, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
437
            new Document(6, ['id' => 1, 'email' => '[email protected]', 'username' => 'marley']),
438
            new Document(7, ['id' => 1, 'email' => '[email protected]', 'username' => 'marley']),
439
            new Document(8, ['id' => 1, 'email' => '[email protected]', 'username' => 'marley']),
440
            new Document(9, ['id' => 1, 'email' => '[email protected]', 'username' => 'marley']),
441
            new Document(10, ['id' => 1, 'email' => '[email protected]', 'username' => 'marley']),
442
            new Document(11, ['id' => 1, 'email' => '[email protected]', 'username' => 'marley']),
443
        ]);
444
        $index->refresh();
445
446
        $search->addIndex($index);
447
448
        $count = $search->count('farrelley');
449
        $this->assertEquals(5, $count);
450
451
        $count = $search->count('marley');
452
        $this->assertEquals(6, $count);
453
454
        $count = $search->count();
455
        $this->assertEquals(6, $count, 'Uses previous query set');
456
457
        $count = $search->count(new MatchAll());
458
        $this->assertEquals(11, $count);
459
460
        $count = $search->count('bunny');
461
        $this->assertEquals(0, $count);
462
    }
463
464
    /**
465
     * @group functional
466
     */
467
    public function testCountRequestGet(): void
468
    {
469
        $client = $this->_getClient();
470
        $search = new Search($client);
471
472
        $index = $client->getIndex('zero');
473
        $index->create(
474
            [
475
                'settings' => [
476
                    'index' => [
477
                        'number_of_shards' => 1,
478
                        'number_of_replicas' => 0,
479
                    ],
480
                ],
481
            ],
482
            [
483
                'recreate' => true,
484
            ]
485
        );
486
487
        $index->addDocuments([
488
            new Document(1, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
489
            new Document(2, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
490
            new Document(3, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
491
            new Document(4, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
492
            new Document(5, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
493
            new Document(6, ['id' => 1, 'email' => '[email protected]', 'username' => 'marley']),
494
            new Document(7, ['id' => 1, 'email' => '[email protected]', 'username' => 'marley']),
495
            new Document(8, ['id' => 1, 'email' => '[email protected]', 'username' => 'marley']),
496
            new Document(9, ['id' => 1, 'email' => '[email protected]', 'username' => 'marley']),
497
            new Document(10, ['id' => 1, 'email' => '[email protected]', 'username' => 'marley']),
498
            new Document(11, ['id' => 1, 'email' => '[email protected]', 'username' => 'marley']),
499
        ]);
500
        $index->refresh();
501
502
        $search->addIndex($index);
503
504
        $count = $search->count('farrelley', false, Request::GET);
505
        $this->assertEquals(5, $count);
506
507
        $count = $search->count('marley', false, Request::GET);
508
        $this->assertEquals(6, $count);
509
510
        $count = $search->count('', false, Request::GET);
511
        $this->assertEquals(6, $count, 'Uses previous query set');
512
513
        $count = $search->count(new MatchAll(), false, Request::GET);
0 ignored issues
show
new \Elastica\Query\MatchAll() is of type object<Elastica\Query\MatchAll>, but the function expects a string|array|object<Elastica\Query>.

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...
514
        $this->assertEquals(11, $count);
515
516
        $count = $search->count('bunny', false, Request::GET);
517
        $this->assertEquals(0, $count);
518
    }
519
520
    /**
521
     * @group functional
522
     */
523
    public function testEmptySearch(): void
524
    {
525
        $client = $this->_getClient();
526
        $search = new Search($client);
527
528
        $index = $client->getIndex('zero');
529
        $index->create(
530
            [
531
                'settings' => [
532
                    'index' => [
533
                        'number_of_shards' => 1,
534
                        'number_of_replicas' => 0,
535
                    ],
536
                ],
537
            ],
538
            [
539
                'recreate' => true,
540
            ]
541
        );
542
        $index->addDocuments([
543
            new Document(1, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
544
            new Document(2, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
545
            new Document(3, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
546
            new Document(4, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
547
            new Document(5, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
548
            new Document(6, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
549
            new Document(7, ['id' => 1, 'email' => '[email protected]', 'username' => 'farrelley']),
550
            new Document(8, ['id' => 1, 'email' => '[email protected]', 'username' => 'bunny']),
551
            new Document(9, ['id' => 1, 'email' => '[email protected]', 'username' => 'bunny']),
552
            new Document(10, ['id' => 1, 'email' => '[email protected]', 'username' => 'bunny']),
553
            new Document(11, ['id' => 1, 'email' => '[email protected]', 'username' => 'bunny']),
554
        ]);
555
        $index->refresh();
556
557
        $search->addIndex($index);
558
        $resultSet = $search->search();
559
        $this->assertInstanceOf(ResultSet::class, $resultSet);
560
        $this->assertCount(10, $resultSet);
561
        $this->assertEquals(11, $resultSet->getTotalHits());
562
563
        $query = new QueryString('bunny');
564
        $search->setQuery($query);
565
566
        $resultSet = $search->search();
567
568
        $this->assertCount(4, $resultSet);
569
        $this->assertEquals(4, $resultSet->getTotalHits());
570
        $source = $resultSet->current()->getSource();
571
        $this->assertEquals('bunny', $source['username']);
572
    }
573
574
    /**
575
     * @group functional
576
     */
577
    public function testCount(): void
578
    {
579
        $index = $this->_createIndex();
580
        $search = new Search($index->getClient());
581
582
        $doc = new Document(1, ['id' => 1, 'username' => 'ruflin']);
583
584
        $index->addDocuments([$doc]);
585
        $index->refresh();
586
587
        $search->addIndex($index);
588
589
        $result1 = $search->count(new MatchAll());
590
        $this->assertEquals(1, $result1);
591
592
        $result2 = $search->count(new MatchAll(), true);
593
        $this->assertInstanceOf(ResultSet::class, $result2);
594
        $this->assertEquals(1, $result2->getTotalHits());
595
    }
596
597
    /**
598
     * @group functional
599
     */
600
    public function testIgnoreUnavailableOption(): void
601
    {
602
        $client = $this->_getClient();
603
        $index = $client->getIndex('elastica_7086b4c2ee585bbb6740ece5ed7ece01');
604
        $query = new MatchAll();
605
606
        $search = new Search($client);
607
        $search->addIndex($index);
608
609
        $exception = null;
610
        try {
611
            $search->search($query);
612
            $this->fail('Should raise an Index not found exception');
613
        } catch (ResponseException $e) {
614
            $error = $e->getResponse()->getFullError();
615
616
            $this->assertEquals('index_not_found_exception', $error['type']);
617
            $this->assertEquals('no such index [elastica_7086b4c2ee585bbb6740ece5ed7ece01]', $error['reason']);
618
        }
619
620
        $search->search($query, [Search::OPTION_SEARCH_IGNORE_UNAVAILABLE => true]);
621
    }
622
623
    /**
624
     * @group functional
625
     */
626
    public function testQuerySizeAfterCount(): void
627
    {
628
        $client = $this->_getClient();
629
        $search = new Search($client);
630
631
        $query = new Query(new MatchAll());
632
        $query->setSize(25);
633
634
        $search->count($query);
635
636
        $this->assertEquals(25, $query->getParam('size'));
637
    }
638
}
639