-
-
Notifications
You must be signed in to change notification settings - Fork 842
/
MatchFilter.php
124 lines (116 loc) · 3.92 KB
/
MatchFilter.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
<?php
/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace ApiPlatform\Elasticsearch\Filter;
/**
* The match filter allows to find resources that [match](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html) the specified text on full text fields.
*
* Syntax: `?property[]=value`.
*
* <div data-code-selector>
*
* ```php
* <?php
* // api/src/Entity/Book.php
* use ApiPlatform\Metadata\ApiFilter;
* use ApiPlatform\Metadata\ApiResource;
* use ApiPlatform\Elasticsearch\Filter\MatchFilter;
*
* #[ApiResource]
* #[ApiFilter(MatchFilter::class, properties: ['title'])]
* class Book
* {
* // ...
* }
* ```
*
* ```yaml
* # config/services.yaml
* services:
* book.match_filter:
* parent: 'api_platform.elasticsearch.match_filter'
* arguments: [ { title: ~ } ]
* tags: [ 'api_platform.filter' ]
* # The following are mandatory only if a _defaults section is defined with inverted values.
* # You may want to isolate filters in a dedicated file to avoid adding the following lines (by adding them in the defaults section)
* autowire: false
* autoconfigure: false
* public: false
*
* # api/config/api_platform/resources.yaml
* resources:
* App\Entity\Book:
* - operations:
* ApiPlatform\Metadata\GetCollection:
* filters: ['book.match_filter']
* ```
*
* ```xml
* <?xml version="1.0" encoding="UTF-8" ?>
* <!-- api/config/services.xml -->
* <?xml version="1.0" encoding="UTF-8" ?>
* <container
* xmlns="http://symfony.com/schema/dic/services"
* xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
* xsi:schemaLocation="http://symfony.com/schema/dic/services
* https://symfony.com/schema/dic/services/services-1.0.xsd">
* <services>
* <service id="book.match_filter" parent="api_platform.elasticsearch.match_filter">
* <argument type="collection">
* <argument key="title"/>
* </argument>
* <tag name="api_platform.filter"/>
* </service>
* </services>
* </container>
* <!-- api/config/api_platform/resources.xml -->
* <resources
* xmlns="https://api-platform.com/schema/metadata/resources-3.0"
* xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
* xsi:schemaLocation="https://api-platform.com/schema/metadata/resources-3.0
* https://api-platform.com/schema/metadata/resources-3.0.xsd">
* <resource class="App\Entity\Book">
* <operations>
* <operation class="ApiPlatform\Metadata\GetCollection">
* <filters>
* <filter>book.match_filter</filter>
* </filters>
* </operation>
* </operations>
* </resource>
* </resources>
* ```
*
* </div>
*
* Given that the collection endpoint is `/books`, you can filter books by title content with the following query: `/books?title=Foundation`.
*
* @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html
*
* @author Baptiste Meyer <baptiste.meyer@gmail.com>
*/
final class MatchFilter extends AbstractSearchFilter
{
/**
* {@inheritdoc}
*/
protected function getQuery(string $property, array $values, ?string $nestedPath): array
{
$matches = [];
foreach ($values as $value) {
$matches[] = ['match' => [$property => $value]];
}
$matchQuery = isset($matches[1]) ? ['bool' => ['should' => $matches]] : $matches[0];
if (null !== $nestedPath) {
$matchQuery = ['nested' => ['path' => $nestedPath, 'query' => $matchQuery]];
}
return $matchQuery;
}
}