diff --git a/src/Builders/FilterBuilder.php b/src/Builders/FilterBuilder.php index f185eb7..dbd83cb 100644 --- a/src/Builders/FilterBuilder.php +++ b/src/Builders/FilterBuilder.php @@ -16,6 +16,18 @@ class FilterBuilder extends Builder public $wheres = [ 'must' => [], 'must_not' => [], + 'should' => [], + ]; + + + /** + * The condition array. + * + * @var array + */ + public $functionScore = [ + 'query' => [], + 'functions' => [], ]; /** @@ -341,6 +353,42 @@ public function whereGeoBoundingBox($field, array $value) return $this; } + /** + * Add a whereShould condition. + * + * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-geo-bounding-box-query.html Geo bounding box query + * + * @param string $field + * @param $value + * @return $this + */ + public function whereShould($field, $value) + { + $this->wheres['should'][] = [ + 'match' => [ + $field => $value + ], + ]; + + return $this; + } + + + /** + * Add a function scroe query + * + * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-geo-bounding-box-query.html Geo bounding box query + * + * @param array $value + * @return $this + */ + public function whereFunctionScore($value) + { + $this->functionScore['functions'][] = $value; + + return $this; + } + /** * Add a whereGeoPolygon condition. * @@ -401,6 +449,18 @@ public function orderBy($field, $direction = 'asc') return $this; } + /** + * Add complex sort array. + * @param array $sort + * @return $this + */ + public function sort($sort) + { + $this->orders[] = $sort; + + return $this; + } + /** * Explain the request. * diff --git a/src/ElasticEngine.php b/src/ElasticEngine.php index b373cb7..008f267 100644 --- a/src/ElasticEngine.php +++ b/src/ElasticEngine.php @@ -106,13 +106,21 @@ public function buildSearchQueryPayloadCollection(Builder $builder, array $optio $payload = new TypePayload($builder->model); if (is_callable($rule)) { - $payload->setIfNotEmpty('body.query.bool', call_user_func($rule, $builder)); + if(count($builder->functionScore['functions']) === 0){ + $payload->setIfNotEmpty('body.query.bool', call_user_func($rule, $builder)); + }else{ + $payload->setIfNotEmpty('body.query', []); + } } else { /** @var SearchRule $ruleEntity */ $ruleEntity = new $rule($builder); if ($ruleEntity->isApplicable()) { - $payload->setIfNotEmpty('body.query.bool', $ruleEntity->buildQueryPayload()); + if(count($builder->functionScore['functions']) === 0){ + $payload->setIfNotEmpty('body.query.bool', $ruleEntity->buildQueryPayload()); + }else{ + $payload->setIfNotEmpty('body.query', []); + } if ($options['highlight'] ?? true) { $payload->setIfNotEmpty('body.highlight', $ruleEntity->buildHighlightPayload()); @@ -125,8 +133,13 @@ public function buildSearchQueryPayloadCollection(Builder $builder, array $optio $payloadCollection->push($payload); } } else { - $payload = (new TypePayload($builder->model)) - ->setIfNotEmpty('body.query.bool.must.match_all', new stdClass()); + if(count($builder->functionScore['functions']) === 0){ + $payload = (new TypePayload($builder->model)) + ->setIfNotEmpty('body.query.bool.must.match_all', new stdClass()); + }else{ + $payload = (new TypePayload($builder->model)) + ->setIfNotEmpty('body.query', []); + } $payloadCollection->push($payload); } @@ -141,17 +154,33 @@ public function buildSearchQueryPayloadCollection(Builder $builder, array $optio ->setIfNotNull('body.from', $builder->offset) ->setIfNotNull('body.size', $builder->limit); - foreach ($builder->wheres as $clause => $filters) { - $clauseKey = 'body.query.bool.filter.bool.'.$clause; + if(count($builder->functionScore['functions']) > 0){ + $payload->setIfNotEmpty('body.query.function_score', $builder->functionScore); + foreach ($builder->wheres as $clause => $filters) { + $clauseKey = 'body.query.function_score.query.bool.'.$clause; - $clauseValue = array_merge( - $payload->get($clauseKey, []), - $filters - ); + $clauseValue = array_merge( + $payload->get($clauseKey, []), + $filters + ); + + $payload->setIfNotEmpty($clauseKey, $clauseValue); + } + } + else{ + foreach ($builder->wheres as $clause => $filters) { + $clauseKey = 'body.query.bool.filter.bool.'.$clause; + + $clauseValue = array_merge( + $payload->get($clauseKey, []), + $filters + ); - $payload->setIfNotEmpty($clauseKey, $clauseValue); + $payload->setIfNotEmpty($clauseKey, $clauseValue); + } } + return $payload->get(); }); } @@ -325,6 +354,10 @@ public function map(Builder $builder, $results, $model) $model->highlight = new Highlight($hit['highlight']); } + if (isset($hit['sort'])) { + $model->sort = $hit['sort']; + } + return $model; } })