Completed
Push — develop ( b42da4...c15277 )
by Sam
13s
created

MatchQuery   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 308
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 33
dl 0
loc 308
rs 9.3999
c 0
b 0
f 0

19 Methods

Rating   Name   Duplication   Size   Complexity  
A toArray() 0 11 3
A getZeroTermsQuery() 0 3 1
A getOperator() 0 3 1
A setOperator() 0 4 1
A setZeroTermsQuery() 0 4 1
A getCutOffFrequency() 0 3 1
A setCutOffFrequency() 0 5 1
A getSlop() 0 3 1
A setAnalyzer() 0 4 1
A getMaxExpansions() 0 3 1
D applyOptions() 0 34 9
A assertSlop() 0 6 2
A assertMaxExpansions() 0 6 2
A setSlop() 0 5 1
A setMaxExpansions() 0 5 1
A assertType() 0 8 2
A getAnalyzer() 0 3 1
A assertCutOffFrequency() 0 6 2
A setType() 0 4 1
1
<?php namespace Nord\Lumen\Elasticsearch\Search\Query\FullText;
2
3
use Nord\Lumen\Elasticsearch\Exceptions\InvalidArgument;
4
use Nord\Lumen\Elasticsearch\Search\Traits\HasField;
5
use Nord\Lumen\Elasticsearch\Search\Query\Traits\HasType;
6
use Nord\Lumen\Elasticsearch\Search\Query\Traits\HasValue;
7
8
/**
9
 * A family of match queries that accepts text/numerics/dates, analyzes them, and constructs a query.
10
 *
11
 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html
12
 */
13
class MatchQuery extends AbstractQuery
14
{
15
    use HasField;
16
    use HasType;
17
    use HasValue;
18
    
19
    const OPERATOR_OR = 'or';
20
    const OPERATOR_AND = 'and';
21
22
    const ZERO_TERM_QUERY_NONE = 'none';
23
    const ZERO_TERM_QUERY_ALL = 'all';
24
25
    const TYPE_PHRASE = 'phrase';
26
    const TYPE_PHRASE_PREFIX = 'phrase_prefix';
27
28
    /**
29
     * @var string The operator flag can be set to "or" or "and" to control the boolean clauses (defaults to "or").
30
     */
31
    private $operator;
32
33
    /**
34
     * @var string If the analyzer used removes all tokens in a query like a "stop" filter does, the default behavior
35
     * is to match no documents at all. In order to change that the zero_terms_query option can be used, which accepts
36
     * "none" (default) and "all" which corresponds to a "match_all" query.
37
     */
38
    private $zeroTermsQuery;
39
40
    /**
41
     * @var float The match query supports a cutoff_frequency that allows specifying an absolute or relative document
42
     * frequency where high frequency terms are moved into an optional subquery and are only scored if one of the low
43
     * frequency (below the cutoff) terms in the case of an or operator or all of the low frequency terms in the case
44
     * of an and operator match.
45
     */
46
    private $cutOffFrequency;
47
48
    /**
49
     * @var int A phrase query matches terms up to a configurable slop (which defaults to 0) in any order.
50
     * Transposed terms have a slop of 2.
51
     */
52
    private $slop;
53
54
    /**
55
     * @var int A "phrase_prefix" query option that controls to how many prefixes the last term will be expanded.
56
     * It is highly recommended to set it to an acceptable value to control the execution time of the query.
57
     */
58
    private $maxExpansions;
59
60
    /**
61
     * @var string The analyzer can be set to control which analyzer will perform the analysis process on the text. It
62
     * defaults to the field explicit mapping definition, or the default search analyzer,
63
     */
64
    private $analyzer;
65
66
    /**
67
     * @inheritdoc
68
     */
69
    public function toArray()
70
    {
71
        $match = ['query' => $this->getValue()];
72
73
        $match = $this->applyOptions($match);
74
75
        if (count($match) === 1 && isset($match['query'])) {
76
            $match = $match['query'];
77
        }
78
79
        return ['match' => [$this->getField() => $match]];
80
    }
81
82
83
    /**
84
     * @param string $operator
85
     * @return MatchQuery
86
     * @throws InvalidArgument
87
     */
88
    public function setOperator($operator)
89
    {
90
        $this->operator = $operator;
91
        return $this;
92
    }
93
94
95
    /**
96
     * @return string
97
     */
98
    public function getOperator()
99
    {
100
        return $this->operator;
101
    }
102
103
104
    /**
105
     * @param string $zeroTermsQuery
106
     * @return MatchQuery
107
     * @throws InvalidArgument
108
     */
109
    public function setZeroTermsQuery($zeroTermsQuery)
110
    {
111
        $this->zeroTermsQuery = $zeroTermsQuery;
112
        return $this;
113
    }
114
115
116
    /**
117
     * @return string
118
     */
119
    public function getZeroTermsQuery()
120
    {
121
        return $this->zeroTermsQuery;
122
    }
123
124
125
    /**
126
     * @param float $cutOffFrequency
127
     * @return MatchQuery
128
     * @throws InvalidArgument
129
     */
130
    public function setCutOffFrequency($cutOffFrequency)
131
    {
132
        $this->assertCutOffFrequency($cutOffFrequency);
133
        $this->cutOffFrequency = $cutOffFrequency;
134
        return $this;
135
    }
136
137
138
    /**
139
     * @return float
140
     */
141
    public function getCutOffFrequency()
142
    {
143
        return $this->cutOffFrequency;
144
    }
145
146
147
    /**
148
     * @param string $type
149
     * @return MatchQuery
150
     * @throws InvalidArgument
151
     */
152
    public function setType($type)
153
    {
154
        $this->type = $type;
155
        return $this;
156
    }
157
158
159
    /**
160
     * @param int $slop
161
     * @return MatchQuery
162
     * @throws InvalidArgument
163
     */
164
    public function setSlop($slop)
165
    {
166
        $this->assertSlop($slop);
167
        $this->slop = $slop;
168
        return $this;
169
    }
170
171
172
    /**
173
     * @return int
174
     */
175
    public function getSlop()
176
    {
177
        return $this->slop;
178
    }
179
180
181
    /**
182
     * @param int $maxExpansions
183
     * @return MatchQuery
184
     * @throws InvalidArgument
185
     */
186
    public function setMaxExpansions($maxExpansions)
187
    {
188
        $this->assertMaxExpansions($maxExpansions);
189
        $this->maxExpansions = $maxExpansions;
190
        return $this;
191
    }
192
193
194
    /**
195
     * @return int
196
     */
197
    public function getMaxExpansions()
198
    {
199
        return $this->maxExpansions;
200
    }
201
202
203
    /**
204
     * @param string $analyzer
205
     * @return MatchQuery
206
     */
207
    public function setAnalyzer($analyzer)
208
    {
209
        $this->analyzer = $analyzer;
210
        return $this;
211
    }
212
213
214
    /**
215
     * @return string
216
     */
217
    public function getAnalyzer()
218
    {
219
        return $this->analyzer;
220
    }
221
222
223
    /**
224
     * @param array $match
225
     * @return array
226
     */
227
    protected function applyOptions(array $match)
228
    {
229
        $operator = $this->getOperator();
230
        if (!is_null($operator)) {
231
            $match['operator'] = $operator;
232
        }
233
        $zeroTermsQuery = $this->getZeroTermsQuery();
234
        if (!is_null($zeroTermsQuery)) {
235
            $match['zero_terms_query'] = $zeroTermsQuery;
236
        }
237
        $cutOffFreq = $this->getCutOffFrequency();
238
        if (!is_null($cutOffFreq)) {
239
            $match['cutoff_frequency'] = $cutOffFreq;
240
        }
241
        $type = $this->getType();
242
        if (!is_null($type)) {
243
            $match['type'] = $type;
244
            $slop = $this->getSlop();
245
            if (!is_null($slop)) {
246
                $match['slop'] = $slop;
247
            }
248
            if ($match['type'] === self::TYPE_PHRASE_PREFIX) {
249
                $maxExp = $this->getMaxExpansions();
250
                if (!is_null($maxExp)) {
251
                    $match['max_expansions'] = $maxExp;
252
                }
253
            }
254
        }
255
        $analyzer = $this->getAnalyzer();
256
        if (!is_null($analyzer)) {
257
            $match['analyzer'] = $analyzer;
258
        }
259
260
        return $match;
261
    }
262
263
264
    /**
265
     * @param float $cutOffFrequency
266
     * @throws InvalidArgument
267
     */
268
    protected function assertCutOffFrequency($cutOffFrequency)
269
    {
270
        if (!is_float($cutOffFrequency)) {
271
            throw new InvalidArgument(sprintf(
272
                'Match Query `cutoff_frequency` must be a float value, "%s" given.',
273
                gettype($cutOffFrequency)
274
            ));
275
        }
276
    }
277
278
279
    /**
280
     * @param string $type
281
     * @throws InvalidArgument
282
     */
283
    protected function assertType($type)
284
    {
285
        $validTypes = [self::TYPE_PHRASE, self::TYPE_PHRASE_PREFIX];
286
        if (!in_array($type, $validTypes)) {
287
            throw new InvalidArgument(sprintf(
288
                'Match Query `type` must be one of "%s", "%s" given.',
289
                implode(', ', $validTypes),
290
                $type
291
            ));
292
        }
293
    }
294
295
296
    /**
297
     * @param int $slop
298
     * @throws InvalidArgument
299
     */
300
    protected function assertSlop($slop)
301
    {
302
        if (!is_int($slop)) {
303
            throw new InvalidArgument(sprintf(
304
                'Match Query `slop` must be an integer, "%s" given.',
305
                gettype($slop)
306
            ));
307
        }
308
    }
309
310
311
    /**
312
     * @param int $maxExpansions
313
     * @throws InvalidArgument
314
     */
315
    protected function assertMaxExpansions($maxExpansions)
316
    {
317
        if (!is_int($maxExpansions)) {
318
            throw new InvalidArgument(sprintf(
319
                'Match Query `max_expansions` must be an integer, "%s" given.',
320
                gettype($maxExpansions)
321
            ));
322
        }
323
    }
324
}
325