*/ class ResultSet implements \Iterator, \Countable, \ArrayAccess { /** * Current position. * * @var int Current position */ private $_position = 0; /** * Query. * * @var Query Query object */ private $_query; /** * Response. * * @var Response Response object */ private $_response; /** * Results. * * @var Result[] Results */ private $_results; /** * @param Result[] $results */ public function __construct(Response $response, Query $query, $results) { $this->_query = $query; $this->_response = $response; $this->_results = $results; } /** * Returns all results. * * @return Result[] */ public function getResults() { return $this->_results; } /** * Returns all Documents. * * @return Document[] */ public function getDocuments() { $documents = []; foreach ($this->_results as $doc) { $documents[] = $doc->getDocument(); } return $documents; } /** * Returns true if the response contains suggestion results; false otherwise. */ public function hasSuggests(): bool { $data = $this->_response->getData(); return isset($data['suggest']); } /** * Return all suggests. * * @return array suggest results */ public function getSuggests(): array { $data = $this->_response->getData(); return $data['suggest'] ?? []; } /** * Returns whether aggregations exist. */ public function hasAggregations(): bool { $data = $this->_response->getData(); return isset($data['aggregations']); } /** * Returns all aggregation results. */ public function getAggregations(): array { $data = $this->_response->getData(); return $data['aggregations'] ?? []; } /** * Retrieve a specific aggregation from this result set. * * @param string $name the name of the desired aggregation * * @throws Exception\InvalidException if an aggregation by the given name cannot be found */ public function getAggregation(string $name): array { $data = $this->_response->getData(); if (isset($data['aggregations'][$name])) { return $data['aggregations'][$name]; } throw new InvalidException("This result set does not contain an aggregation named {$name}."); } /** * Returns the total number of found hits. */ public function getTotalHits(): int { $data = $this->_response->getData(); return (int) ($data['hits']['total']['value'] ?? 0); } /** * Returns the total number relation of found hits. */ public function getTotalHitsRelation(): string { $data = $this->_response->getData(); return $data['hits']['total']['relation'] ?? 'eq'; } /** * Returns the max score of the results found. */ public function getMaxScore(): float { $data = $this->_response->getData(); return (float) ($data['hits']['max_score'] ?? 0); } /** * Returns the total number of ms for this search to complete. */ public function getTotalTime(): int { $data = $this->_response->getData(); return $data['took'] ?? 0; } /** * Returns the Point-In-Time ID, if available. * * @See: https://www.elastic.co/guide/en/elasticsearch/reference/current/paginate-search-results.html#search-after */ public function getPointInTimeId(): ?string { $data = $this->_response->getData(); return $data['pit_id'] ?? null; } /** * Returns true if the query has timed out. */ public function hasTimedOut(): bool { $data = $this->_response->getData(); return !empty($data['timed_out']); } /** * Returns response object. */ public function getResponse(): Response { return $this->_response; } public function getQuery(): Query { return $this->_query; } /** * Returns size of current set. */ public function count(): int { return \count($this->_results); } /** * Returns size of current suggests. */ public function countSuggests(): int { return \count($this->getSuggests()); } /** * Returns the current object of the set. * * @return Result Set object */ public function current(): Result { return $this->_results[$this->key()]; } /** * Sets pointer (current) to the next item of the set. */ public function next(): void { ++$this->_position; } /** * Returns the position of the current entry. * * @return int Current position */ public function key(): int { return $this->_position; } /** * Check if an object exists at the current position. * * @return bool True if object exists */ public function valid(): bool { return isset($this->_results[$this->key()]); } /** * Resets position to 0, restarts iterator. */ public function rewind(): void { $this->_position = 0; } /** * Whether a offset exists. * * @see http://php.net/manual/en/arrayaccess.offsetexists.php * * @param int $offset */ public function offsetExists($offset): bool { return isset($this->_results[$offset]); } /** * Offset to retrieve. * * @see http://php.net/manual/en/arrayaccess.offsetget.php * * @param int $offset * * @throws Exception\InvalidException If offset doesn't exist */ public function offsetGet($offset): Result { if ($this->offsetExists($offset)) { return $this->_results[$offset]; } throw new InvalidException('Offset does not exist.'); } /** * Offset to set. * * @see http://php.net/manual/en/arrayaccess.offsetset.php * * @param int $offset * @param Result $value * * @throws Exception\InvalidException */ public function offsetSet($offset, $value): void { if (!($value instanceof Result)) { throw new InvalidException('ResultSet is a collection of Result only.'); } if (!isset($this->_results[$offset])) { throw new InvalidException('Offset does not exist.'); } $this->_results[$offset] = $value; } /** * Offset to unset. * * @see http://php.net/manual/en/arrayaccess.offsetunset.php * * @param int $offset */ public function offsetUnset($offset): void { unset($this->_results[$offset]); } }