| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- <?php
- namespace Elastica;
- /**
- * Scroll Iterator.
- *
- * @author Manuel Andreo Garcia <andreo.garcia@gmail.com>
- *
- * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-scroll.html
- */
- class Scroll implements \Iterator
- {
- /**
- * @var string
- */
- public $expiryTime;
- /**
- * @var Search
- */
- protected $_search;
- /**
- * @var string|null
- */
- protected $_nextScrollId;
- /**
- * @var ResultSet|null
- */
- protected $_currentResultSet;
- /**
- * 0: scroll<br>
- * 1: scroll id.
- *
- * @var array
- */
- protected $_options = [null, null];
- private $totalPages = 0;
- private $currentPage = 0;
- /**
- * Constructor.
- *
- * @param Search $search
- * @param string $expiryTime
- */
- public function __construct(Search $search, $expiryTime = '1m')
- {
- $this->_search = $search;
- $this->expiryTime = $expiryTime;
- }
- /**
- * Returns current result set.
- *
- * @see http://php.net/manual/en/iterator.current.php
- *
- * @return ResultSet
- */
- public function current()
- {
- return $this->_currentResultSet;
- }
- /**
- * Next scroll search.
- *
- * @see http://php.net/manual/en/iterator.next.php
- */
- public function next()
- {
- if ($this->currentPage < $this->totalPages) {
- $this->_saveOptions();
- $this->_search->setOption(Search::OPTION_SCROLL, $this->expiryTime);
- $this->_search->setOption(Search::OPTION_SCROLL_ID, $this->_nextScrollId);
- $this->_setScrollId($this->_search->search());
- $this->_revertOptions();
- } else {
- // If there are no pages left, we do not need to query ES.
- $this->clear();
- }
- }
- /**
- * Returns scroll id.
- *
- * @see http://php.net/manual/en/iterator.key.php
- *
- * @return string
- */
- public function key()
- {
- return $this->_nextScrollId;
- }
- /**
- * Returns true if current result set contains at least one hit.
- *
- * @see http://php.net/manual/en/iterator.valid.php
- *
- * @return bool
- */
- public function valid()
- {
- return null !== $this->_nextScrollId;
- }
- /**
- * Initial scroll search.
- *
- * @see http://php.net/manual/en/iterator.rewind.php
- */
- public function rewind()
- {
- // reset state
- $this->_options = [null, null];
- $this->currentPage = 0;
- // initial search
- $this->_saveOptions();
- $this->_search->setOption(Search::OPTION_SCROLL, $this->expiryTime);
- $this->_search->setOption(Search::OPTION_SCROLL_ID, null);
- $this->_setScrollId($this->_search->search());
- $this->_revertOptions();
- }
- /**
- * Cleares the search context on ES and marks this Scroll instance as finished.
- */
- public function clear()
- {
- if (null !== $this->_nextScrollId) {
- $this->_search->getClient()->request(
- '_search/scroll',
- Request::DELETE,
- [Search::OPTION_SCROLL_ID => [$this->_nextScrollId]]
- );
- // Reset scroll ID so valid() returns false.
- $this->_nextScrollId = null;
- $this->_currentResultSet = null;
- }
- }
- /**
- * Prepares Scroll for next request.
- *
- * @param ResultSet $resultSet
- */
- protected function _setScrollId(ResultSet $resultSet)
- {
- if (0 === $this->currentPage) {
- $this->totalPages = $resultSet->count() > 0 ? ceil($resultSet->getTotalHits() / $resultSet->count()) : 0;
- }
- $this->_currentResultSet = $resultSet;
- ++$this->currentPage;
- $this->_nextScrollId = $resultSet->getResponse()->isOk() && $resultSet->count() > 0 ? $resultSet->getResponse()->getScrollId() : null;
- }
- /**
- * Save all search options manipulated by Scroll.
- */
- protected function _saveOptions()
- {
- if ($this->_search->hasOption(Search::OPTION_SCROLL)) {
- $this->_options[0] = $this->_search->getOption(Search::OPTION_SCROLL);
- }
- if ($this->_search->hasOption(Search::OPTION_SCROLL_ID)) {
- $this->_options[1] = $this->_search->getOption(Search::OPTION_SCROLL_ID);
- }
- }
- /**
- * Revert search options to previously saved state.
- */
- protected function _revertOptions()
- {
- $this->_search->setOption(Search::OPTION_SCROLL, $this->_options[0]);
- $this->_search->setOption(Search::OPTION_SCROLL_ID, $this->_options[1]);
- }
- }
|