1<?php 2 3namespace Elastica; 4 5use Elastica\Aggregation\AbstractAggregation; 6use Elastica\Exception\InvalidException; 7use Elastica\Query\AbstractQuery; 8use Elastica\Query\MatchAll; 9use Elastica\Query\QueryString; 10use Elastica\Script\AbstractScript; 11use Elastica\Script\ScriptFields; 12use Elastica\Suggest\AbstractSuggest; 13 14/** 15 * Elastica query object. 16 * 17 * Creates different types of queries 18 * 19 * @author Nicolas Ruflin <spam@ruflin.com> 20 * 21 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-body.html 22 */ 23class Query extends Param 24{ 25 /** 26 * Suggest query or not. 27 * 28 * @var int Suggest 29 */ 30 protected $_suggest = 0; 31 32 /** 33 * Creates a query object. 34 * 35 * @param array|\Elastica\Query\AbstractQuery $query OPTIONAL Query object (default = null) 36 */ 37 public function __construct($query = null) 38 { 39 if (\is_array($query)) { 40 $this->setRawQuery($query); 41 } elseif ($query instanceof AbstractQuery) { 42 $this->setQuery($query); 43 } elseif ($query instanceof Suggest) { 44 $this->setSuggest($query); 45 } 46 } 47 48 /** 49 * Transforms the argument to a query object. 50 * 51 * For example, an empty argument will return a \Elastica\Query with a \Elastica\Query\MatchAll. 52 * 53 * @param mixed $query 54 * 55 * @throws InvalidException For an invalid argument 56 * 57 * @return self 58 */ 59 public static function create($query) 60 { 61 switch (true) { 62 case $query instanceof self: 63 return $query; 64 case $query instanceof AbstractQuery: 65 return new self($query); 66 case empty($query): 67 return new self(new MatchAll()); 68 case \is_array($query): 69 return new self($query); 70 case \is_string($query): 71 return new self(new QueryString($query)); 72 case $query instanceof AbstractSuggest: 73 return new self(new Suggest($query)); 74 75 case $query instanceof Suggest: 76 return new self($query); 77 } 78 79 throw new InvalidException('Unexpected argument to create a query for.'); 80 } 81 82 /** 83 * Sets query as raw array. Will overwrite all already set arguments. 84 * 85 * @param array $query Query array 86 * 87 * @return $this 88 */ 89 public function setRawQuery(array $query) 90 { 91 $this->_params = $query; 92 93 return $this; 94 } 95 96 /** 97 * Sets the query. 98 * 99 * @param \Elastica\Query\AbstractQuery $query Query object 100 * 101 * @return $this 102 */ 103 public function setQuery(AbstractQuery $query) 104 { 105 return $this->setParam('query', $query); 106 } 107 108 /** 109 * Gets the query object. 110 * 111 * @return \Elastica\Query\AbstractQuery 112 **/ 113 public function getQuery() 114 { 115 return $this->getParam('query'); 116 } 117 118 /** 119 * Sets the start from which the search results should be returned. 120 * 121 * @param int $from 122 * 123 * @return $this 124 */ 125 public function setFrom($from) 126 { 127 return $this->setParam('from', $from); 128 } 129 130 /** 131 * Sets sort arguments for the query 132 * Replaces existing values. 133 * 134 * @param array $sortArgs Sorting arguments 135 * 136 * @return $this 137 * 138 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html 139 */ 140 public function setSort(array $sortArgs) 141 { 142 return $this->setParam('sort', $sortArgs); 143 } 144 145 /** 146 * Adds a sort param to the query. 147 * 148 * @param mixed $sort Sort parameter 149 * 150 * @return $this 151 * 152 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html 153 */ 154 public function addSort($sort) 155 { 156 return $this->addParam('sort', $sort); 157 } 158 159 /** 160 * Keep track of the scores when sorting results. 161 * 162 * @param bool $trackScores 163 * 164 * @return $this 165 * 166 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html#_track_scores 167 */ 168 public function setTrackScores($trackScores = true) 169 { 170 return $this->setParam('track_scores', (bool) $trackScores); 171 } 172 173 /** 174 * Sets highlight arguments for the query. 175 * 176 * @param array $highlightArgs Set all highlight arguments 177 * 178 * @return $this 179 * 180 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-highlighting.html 181 */ 182 public function setHighlight(array $highlightArgs) 183 { 184 return $this->setParam('highlight', $highlightArgs); 185 } 186 187 /** 188 * Adds a highlight argument. 189 * 190 * @param mixed $highlight Add highlight argument 191 * 192 * @return $this 193 * 194 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-highlighting.html 195 */ 196 public function addHighlight($highlight) 197 { 198 return $this->addParam('highlight', $highlight); 199 } 200 201 /** 202 * Sets maximum number of results for this query. 203 * 204 * @param int $size OPTIONAL Maximal number of results for query (default = 10) 205 * 206 * @return $this 207 */ 208 public function setSize($size = 10) 209 { 210 return $this->setParam('size', $size); 211 } 212 213 /** 214 * Enables explain on the query. 215 * 216 * @param bool $explain OPTIONAL Enabled or disable explain (default = true) 217 * 218 * @return $this 219 * 220 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-explain.html 221 */ 222 public function setExplain($explain = true) 223 { 224 return $this->setParam('explain', $explain); 225 } 226 227 /** 228 * Enables version on the query. 229 * 230 * @param bool $version OPTIONAL Enabled or disable version (default = true) 231 * 232 * @return $this 233 * 234 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-version.html 235 */ 236 public function setVersion($version = true) 237 { 238 return $this->setParam('version', $version); 239 } 240 241 /** 242 * Sets the fields to be returned by the search 243 * NOTICE php will encode modified(or named keys) array into object format in json format request 244 * so the fields array must a sequence(list) type of array. 245 * 246 * @param array $fields Fields to be returned 247 * 248 * @return $this 249 * 250 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-fields.html 251 */ 252 public function setStoredFields(array $fields) 253 { 254 return $this->setParam('stored_fields', $fields); 255 } 256 257 /** 258 * Sets the fields not stored to be returned by the search. 259 * 260 * @param array $fieldDataFields Fields not stored to be returned 261 * 262 * @return $this 263 * 264 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-fielddata-fields.html 265 */ 266 public function setFieldDataFields(array $fieldDataFields) 267 { 268 return $this->setParam('docvalue_fields', $fieldDataFields); 269 } 270 271 /** 272 * Set script fields. 273 * 274 * @param array|\Elastica\Script\ScriptFields $scriptFields Script fields 275 * 276 * @return $this 277 * 278 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-script-fields.html 279 */ 280 public function setScriptFields($scriptFields) 281 { 282 if (\is_array($scriptFields)) { 283 $scriptFields = new ScriptFields($scriptFields); 284 } 285 286 return $this->setParam('script_fields', $scriptFields); 287 } 288 289 /** 290 * Adds a Script to the query. 291 * 292 * @param string $name 293 * @param \Elastica\Script\AbstractScript $script Script object 294 * 295 * @return $this 296 */ 297 public function addScriptField($name, AbstractScript $script) 298 { 299 if (isset($this->_params['script_fields'])) { 300 $this->_params['script_fields']->addScript($name, $script); 301 } else { 302 $this->setScriptFields([$name => $script]); 303 } 304 305 return $this; 306 } 307 308 /** 309 * Adds an Aggregation to the query. 310 * 311 * @param AbstractAggregation $agg 312 * 313 * @return $this 314 */ 315 public function addAggregation(AbstractAggregation $agg) 316 { 317 $this->_params['aggs'][] = $agg; 318 319 return $this; 320 } 321 322 /** 323 * Converts all query params to an array. 324 * 325 * @return array Query array 326 */ 327 public function toArray() 328 { 329 if (!isset($this->_params['query']) && (0 == $this->_suggest)) { 330 $this->setQuery(new MatchAll()); 331 } 332 333 if (isset($this->_params['post_filter']) && 0 === \count(($this->_params['post_filter'])->toArray())) { 334 unset($this->_params['post_filter']); 335 } 336 337 $array = $this->_convertArrayable($this->_params); 338 339 if (isset($array['suggest'])) { 340 $array['suggest'] = $array['suggest']['suggest']; 341 } 342 343 return $array; 344 } 345 346 /** 347 * Allows filtering of documents based on a minimum score. 348 * 349 * @param float $minScore Minimum score to filter documents by 350 * 351 * @throws \Elastica\Exception\InvalidException 352 * 353 * @return $this 354 */ 355 public function setMinScore($minScore) 356 { 357 if (!\is_numeric($minScore)) { 358 throw new InvalidException('has to be numeric param'); 359 } 360 361 return $this->setParam('min_score', $minScore); 362 } 363 364 /** 365 * Add a suggest term. 366 * 367 * @param \Elastica\Suggest $suggest suggestion object 368 * 369 * @return $this 370 */ 371 public function setSuggest(Suggest $suggest) 372 { 373 $this->setParam('suggest', $suggest); 374 375 $this->_suggest = 1; 376 377 return $this; 378 } 379 380 /** 381 * Add a Rescore. 382 * 383 * @param mixed $rescore suggestion object 384 * 385 * @return $this 386 */ 387 public function setRescore($rescore) 388 { 389 if (\is_array($rescore)) { 390 $buffer = []; 391 392 foreach ($rescore as $rescoreQuery) { 393 $buffer[] = $rescoreQuery; 394 } 395 } else { 396 $buffer = $rescore; 397 } 398 399 return $this->setParam('rescore', $buffer); 400 } 401 402 /** 403 * Sets the _source field to be returned with every hit. 404 * 405 * @param array|bool $params Fields to be returned or false to disable source 406 * 407 * @return $this 408 * 409 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-source-filtering.html 410 */ 411 public function setSource($params) 412 { 413 return $this->setParam('_source', $params); 414 } 415 416 /** 417 * Sets post_filter argument for the query. The filter is applied after the query has executed. 418 * 419 * @param array|\Elastica\Query\AbstractQuery $filter 420 * 421 * @return $this 422 * 423 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-post-filter.html 424 */ 425 public function setPostFilter(AbstractQuery $filter) 426 { 427 return $this->setParam('post_filter', $filter); 428 } 429} 430