Completed
Pull Request — develop (#63)
by Sam
01:30
created

MatchQuery::getOperator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
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->assertType($type);
155
        $this->type = $type;
156
        return $this;
157
    }
158
159
160
    /**
161
     * @param int $slop
162
     * @return MatchQuery
163
     * @throws InvalidArgument
164
     */
165
    public function setSlop($slop)
166
    {
167
        $this->assertSlop($slop);
168
        $this->slop = $slop;
169
        return $this;
170
    }
171
172
173
    /**
174
     * @return int
175
     */
176
    public function getSlop()
177
    {
178
        return $this->slop;
179
    }
180
181
182
    /**
183
     * @param int $maxExpansions
184
     * @return MatchQuery
185
     * @throws InvalidArgument
186
     */
187
    public function setMaxExpansions($maxExpansions)
188
    {
189
        $this->assertMaxExpansions($maxExpansions);
190
        $this->maxExpansions = $maxExpansions;
191
        return $this;
192
    }
193
194
195
    /**
196
     * @return int
197
     */
198
    public function getMaxExpansions()
199
    {
200
        return $this->maxExpansions;
201
    }
202
203
204
    /**
205
     * @param string $analyzer
206
     * @return MatchQuery
207
     */
208
    public function setAnalyzer($analyzer)
209
    {
210
        $this->analyzer = $analyzer;
211
        return $this;
212
    }
213
214
215
    /**
216
     * @return string
217
     */
218
    public function getAnalyzer()
219
    {
220
        return $this->analyzer;
221
    }
222
223
224
    /**
225
     * @param array $match
226
     * @return array
227
     */
228
    protected function applyOptions(array $match)
229
    {
230
        $operator = $this->getOperator();
231
        if (!is_null($operator)) {
232
            $match['operator'] = $operator;
233
        }
234
        $zeroTermsQuery = $this->getZeroTermsQuery();
235
        if (!is_null($zeroTermsQuery)) {
236
            $match['zero_terms_query'] = $zeroTermsQuery;
237
        }
238
        $cutOffFreq = $this->getCutOffFrequency();
239
        if (!is_null($cutOffFreq)) {
240
            $match['cutoff_frequency'] = $cutOffFreq;
241
        }
242
        $type = $this->getType();
243
        if (!is_null($type)) {
244
            $match['type'] = $type;
245
            $slop = $this->getSlop();
246
            if (!is_null($slop)) {
247
                $match['slop'] = $slop;
248
            }
249
            if ($match['type'] === self::TYPE_PHRASE_PREFIX) {
250
                $maxExp = $this->getMaxExpansions();
251
                if (!is_null($maxExp)) {
252
                    $match['max_expansions'] = $maxExp;
253
                }
254
            }
255
        }
256
        $analyzer = $this->getAnalyzer();
257
        if (!is_null($analyzer)) {
258
            $match['analyzer'] = $analyzer;
259
        }
260
261
        return $match;
262
    }
263
264
265
    /**
266
     * @param float $cutOffFrequency
267
     * @throws InvalidArgument
268
     */
269
    protected function assertCutOffFrequency($cutOffFrequency)
270
    {
271
        if (!is_float($cutOffFrequency)) {
272
            throw new InvalidArgument(sprintf(
273
                'Match Query `cutoff_frequency` must be a float value, "%s" given.',
274
                gettype($cutOffFrequency)
275
            ));
276
        }
277
    }
278
279
280
    /**
281
     * @param string $type
282
     * @throws InvalidArgument
283
     */
284
    protected function assertType($type)
285
    {
286
        $validTypes = [self::TYPE_PHRASE, self::TYPE_PHRASE_PREFIX];
287
        if (!in_array($type, $validTypes)) {
288
            throw new InvalidArgument(sprintf(
289
                'Match Query `type` must be one of "%s", "%s" given.',
290
                implode(', ', $validTypes),
291
                $type
292
            ));
293
        }
294
    }
295
296
297
    /**
298
     * @param int $slop
299
     * @throws InvalidArgument
300
     */
301
    protected function assertSlop($slop)
302
    {
303
        if (!is_int($slop)) {
304
            throw new InvalidArgument(sprintf(
305
                'Match Query `slop` must be an integer, "%s" given.',
306
                gettype($slop)
307
            ));
308
        }
309
    }
310
311
312
    /**
313
     * @param int $maxExpansions
314
     * @throws InvalidArgument
315
     */
316
    protected function assertMaxExpansions($maxExpansions)
317
    {
318
        if (!is_int($maxExpansions)) {
319
            throw new InvalidArgument(sprintf(
320
                'Match Query `max_expansions` must be an integer, "%s" given.',
321
                gettype($maxExpansions)
322
            ));
323
        }
324
    }
325
}
326