Passed
Push — master ( 7760cd...612ec5 )
by
unknown
05:04
created

Search::match()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
c 0
b 0
f 0
nc 2
nop 2
dl 0
loc 8
rs 10
1
<?php
2
3
4
namespace Manticoresearch;
5
6
use Manticoresearch\Query\BoolQuery;
7
use Manticoresearch\Query\Distance;
8
use Manticoresearch\Query\Equals;
9
use Manticoresearch\Query\In;
10
use Manticoresearch\Query\MatchQuery;
11
use Manticoresearch\Query\MatchPhrase;
12
use Manticoresearch\Query\QueryString;
13
use Manticoresearch\Query\Range;
14
use Manticoresearch\Query\ScriptFields;
15
16
/**
17
 * Manticore search object
18
 * @category ManticoreSearch
19
 * @package ManticoreSearch
20
 * @author Adrian Nuta <[email protected]>
21
 * @link https://manticoresearch.com
22
 */
23
class Search
24
{
25
    const FILTER_AND = "AND";
26
    const FILTER_OR = "OR";
27
    const FILTER_NOT = "NOT";
28
29
    /**
30
     * @var Client
31
     */
32
    protected $client;
33
34
    protected $query;
35
    protected $body;
36
    /**
37
     * @var array
38
     */
39
    protected $params = [];
40
41
    protected static $replaceOperator = [
42
        '=' => 'equals',
43
        '>=' => 'gte',
44
        '>' => 'gt',
45
        '<' => 'lt',
46
        '<=' => 'lte',
47
    ];
48
49
    public function __construct(Client $client)
50
    {
51
        $this->client = $client;
52
        $this->query = new BoolQuery();
53
    }
54
55
    public function setIndex($index): self
56
    {
57
        $this->params['index'] = $index;
58
        return $this;
59
    }
60
61
    public function setSource($source): self
62
    {
63
        $this->params['_source'] = $source;
64
        return $this;
65
    }
66
67
    public function trackScores($trackScores): self
68
    {
69
        if (is_null($trackScores)) {
70
            unset($this->params['track_scores']);
71
        } else {
72
            $this->params['track_scores'] = (bool)$trackScores;
73
        }
74
75
        return $this;
76
    }
77
78
    public function stripBadUtf8($stripBadUtf8): self
79
    {
80
        if (is_null($stripBadUtf8)) {
81
            unset($this->params['strip_bad_utf8']);
82
        } else {
83
            $this->params['strip_bad_utf8'] = (bool)$stripBadUtf8;
84
        }
85
        
86
        return $this;
87
    }
88
    
89
    /**
90
     * @param string $queryString
91
     * @return $this
92
     */
93
    public function search($queryString): self
94
    {
95
        if (is_object($queryString)) {
0 ignored issues
show
introduced by
The condition is_object($queryString) is always false.
Loading history...
96
            $this->query = $queryString;
97
            return $this;
98
        }
99
        $this->query->must(new QueryString($queryString));
100
        return $this;
101
    }
102
103
    public function match($keywords, $fields = null): self
104
    {
105
        $f = "*";
106
        if ($fields !== null && is_string($fields)) {
107
            $f = $fields;
108
        }
109
        $this->query->must(new MatchQuery($keywords, $f));
110
        return $this;
111
    }
112
113
    public function phrase($string, $fields = null): self
114
    {
115
        $f = "*";
116
        if ($fields !== null && is_string($fields)) {
117
            $f = $fields;
118
        }
119
        $this->query->must(new MatchPhrase($string, $f));
120
        return $this;
121
    }
122
123
    public function limit($limit): self
124
    {
125
        $this->params['limit'] = $limit;
126
        return $this;
127
    }
128
129
    /**
130
     * @param string $name
131
     * @param string $exp
132
     * @return $this
133
     */
134
    public function expression($name, $exp): self
135
    {
136
        if (!isset($this->params['script_fields'])) {
137
            $this->params['script_fields'] = new ScriptFields();
138
        }
139
        $this->params['script_fields']->add($name, $exp);
140
        return $this;
141
    }
142
143
    public function highlight($fields = [], $settings = []): self
144
    {
145
146
        if (count($fields) === 0 && count($settings)===0) {
147
            $this->params['highlight'] =  new \stdClass();
148
            return $this;
149
        }
150
        $this->params['highlight'] = [];
151
        if (count($fields) > 0) {
152
            $this->params['highlight']['fields'] =$fields;
153
        }
154
        if (count($settings)>0) {
155
            foreach ($settings as $name => $value) {
156
                $this->params['highlight'][$name] =$value;
157
            }
158
        }
159
        return $this;
160
    }
161
162
    public function distance($args): self
163
    {
164
        $this->query->must(new Distance($args));
165
        return $this;
166
    }
167
168
    protected function getAttrObject($attr, $op, $values)
169
    {
170
        $op = static::$replaceOperator[$op] ?? $op;
171
172
        switch ($op) {
173
            case 'range':
174
                $object = new Range($attr, [
175
                    'gte' => $values[0],
176
                    'lte' => $values[1]
177
                ]);
178
                break;
179
            case 'lt':
180
            case 'lte':
181
            case 'gt':
182
            case 'gte':
183
                $object = new Range($attr, [
184
                    $op => $values[0],
185
                ]);
186
                break;
187
            case 'in':
188
                $object = new In($attr, $values);
189
                break;
190
            case 'equals':
191
                $object = new Equals($attr, $values[0]);
192
                break;
193
            default:
194
                $object = null;
195
        }
196
197
        return $object;
198
    }
199
200
    public function filter($attr, $op = null, $values = null, $boolean = self::FILTER_AND): self
201
    {
202
        if (!is_object($attr)) {
203
            if (is_null($values)) {
204
                $values = $op;
205
                $op = "equals";
206
            }
207
208
            if (!is_array($values)) {
209
                $values = [$values];
210
            }
211
212
            $attr = $this->getAttrObject($attr, $op, $values);
213
214
            if (!$attr) {
215
                return $this;
216
            }
217
        }
218
219
        if ($boolean === self::FILTER_AND) {
220
            $this->query->must($attr);
221
        } elseif ($boolean === self::FILTER_OR) {
222
            $this->query->should($attr);
223
        } elseif ($boolean === self::FILTER_NOT) {
224
            $this->query->mustNot($attr);
225
        }
226
227
        return $this;
228
    }
229
230
    public function orFilter($attr, $op = null, $values = null): self
231
    {
232
        return $this->filter($attr, $op, $values, self::FILTER_OR);
233
    }
234
235
    public function notFilter($attr, $op = null, $values = null): self
236
    {
237
        return $this->filter($attr, $op, $values, self::FILTER_NOT);
238
    }
239
240
    public function offset($offset): self
241
    {
242
        $this->params['offset'] = $offset;
243
        return $this;
244
    }
245
246
    public function maxMatches($maxmatches): self
247
    {
248
        $this->params['max_matches'] = $maxmatches;
249
        return $this;
250
    }
251
252
    public function facet($field, $group = null, $limit = null) : self
253
    {
254
        // reset facets
255
        if ($field === false) {
256
            $this->params['aggs'] = [];
257
        }
258
        if ($group === null) {
259
            $group = $field;
260
        }
261
        $terms = ['field'=>$field];
262
        if ($limit !==null) {
263
            $terms['size'] = $limit;
264
        }
265
        $this->params['aggs'][$group] =['terms' =>$terms];
266
        return $this;
267
    }
268
269
    public function sort($field, $direction = 'asc', $mode = null): self
270
    {
271
        // reset sorting
272
        if ($field === false) {
273
            $this->params['sort'] = [];
274
        }
275
        //if 1st arg is array means we have a sorting expression
276
        if (is_array($field)) {
277
            //is 2nd arg is true we full set the sort with the expr, otherwise just add it
278
            if (isset($direction) && $direction === true) {
279
                $this->params['sort'] = $field;
280
            } else {
281
                $this->params['sort'] [] = $field;
282
            }
283
            return $this;
284
        }
285
        if (!isset($this->params['sort'])) {
286
            $this->params['sort'] = [];
287
        }
288
        if ($mode === null) {
289
            $this->params['sort'] [] = [$field => $direction];
290
        } else {
291
            $this->params['sort'] [] = [$field => ['order' => $direction, 'mode' => $mode]];
292
        }
293
294
        return $this;
295
    }
296
297
    public function option($name, $value): self
298
    {
299
        if (is_null($value)) {
300
            unset($this->params['options'][$name]);
301
        } else {
302
            $this->params['options'][$name] = $value;
303
        }
304
305
        return $this;
306
    }
307
308
    public function profile(): self
309
    {
310
        $this->params['profile'] = true;
311
        return $this;
312
    }
313
314
    /**
315
     * @return ResultSet
316
     */
317
    public function get()
318
    {
319
        $this->body = $this->compile();
320
        $resp = $this->client->search(['body' => $this->body], true);
321
        return new ResultSet($resp);
322
    }
323
324
    public function compile()
325
    {
326
        $body = $this->params;
327
        $query = $this->query->toArray();
328
        if ($query !== null) {
329
            $body['query'] = $query;
330
        }
331
332
        if (isset($this->params['script_fields'])) {
333
            $body['script_fields'] = $this->params['script_fields']->toArray();
334
            unset($this->params['script_fields']);
335
        }
336
337
        return $body;
338
    }
339
340
    public function getBody()
341
    {
342
        return $this->body;
343
    }
344
345
    public function reset()
346
    {
347
        $this->params = [];
348
        $this->query = new BoolQuery();
349
    }
350
351
    public function getClient()
352
    {
353
        return $this->client;
354
    }
355
}
356