SearchHitIterator.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. <?php
  2. namespace Elasticsearch\Helper\Iterators;
  3. use Iterator;
  4. /**
  5. * Class SearchHitIterator
  6. *
  7. * @category Elasticsearch
  8. * @package Elasticsearch\Helper\Iterators
  9. * @author Arturo Mejia <arturo.mejia@kreatetechnology.com>
  10. * @license http://www.apache.org/licenses/LICENSE-2.0 Apache2
  11. * @link http://elastic.co
  12. * @see Iterator
  13. */
  14. class SearchHitIterator implements Iterator, \Countable
  15. {
  16. /**
  17. * @var SearchResponseIterator
  18. */
  19. private $search_responses;
  20. /**
  21. * @var int
  22. */
  23. protected $current_key;
  24. /**
  25. * @var int
  26. */
  27. protected $current_hit_index;
  28. /**
  29. * @var array|null
  30. */
  31. protected $current_hit_data;
  32. /**
  33. * @var int
  34. */
  35. protected $count;
  36. /**
  37. * Constructor
  38. *
  39. * @param SearchResponseIterator $search_responses
  40. */
  41. public function __construct(SearchResponseIterator $search_responses)
  42. {
  43. $this->search_responses = $search_responses;
  44. }
  45. /**
  46. * Rewinds the internal SearchResponseIterator and itself
  47. *
  48. * @return void
  49. * @see Iterator::rewind()
  50. */
  51. public function rewind()
  52. {
  53. $this->current_key = 0;
  54. $this->search_responses->rewind();
  55. // The first page may be empty. In that case, the next page is fetched.
  56. $current_page = $this->search_responses->current();
  57. if ($this->search_responses->valid() && empty($current_page['hits']['hits'])) {
  58. $this->search_responses->next();
  59. }
  60. $this->count = 0;
  61. if (isset($current_page['hits']) && isset($current_page['hits']['total'])) {
  62. $this->count = $current_page['hits']['total'];
  63. }
  64. $this->readPageData();
  65. }
  66. /**
  67. * Advances pointer of the current hit to the next one in the current page. If there
  68. * isn't a next hit in the current page, then it advances the current page and moves the
  69. * pointer to the first hit in the page.
  70. *
  71. * @return void
  72. * @see Iterator::next()
  73. */
  74. public function next()
  75. {
  76. $this->current_key++;
  77. $this->current_hit_index++;
  78. $current_page = $this->search_responses->current();
  79. if (isset($current_page['hits']['hits'][$this->current_hit_index])) {
  80. $this->current_hit_data = $current_page['hits']['hits'][$this->current_hit_index];
  81. } else {
  82. $this->search_responses->next();
  83. $this->readPageData();
  84. }
  85. }
  86. /**
  87. * Returns a boolean indicating whether or not the current pointer has valid data
  88. *
  89. * @return bool
  90. * @see Iterator::valid()
  91. */
  92. public function valid()
  93. {
  94. return is_array($this->current_hit_data);
  95. }
  96. /**
  97. * Returns the current hit
  98. *
  99. * @return array
  100. * @see Iterator::current()
  101. */
  102. public function current()
  103. {
  104. return $this->current_hit_data;
  105. }
  106. /**
  107. * Returns the current hit index. The hit index spans all pages.
  108. *
  109. * @return int
  110. * @see Iterator::key()
  111. */
  112. public function key()
  113. {
  114. return $this->current_hit_index;
  115. }
  116. /**
  117. * Advances the internal SearchResponseIterator and resets the current_hit_index to 0
  118. *
  119. * @internal
  120. */
  121. private function readPageData()
  122. {
  123. if ($this->search_responses->valid()) {
  124. $current_page = $this->search_responses->current();
  125. $this->current_hit_index = 0;
  126. $this->current_hit_data = $current_page['hits']['hits'][$this->current_hit_index];
  127. } else {
  128. $this->current_hit_data = null;
  129. }
  130. }
  131. /**
  132. * {@inheritDoc}
  133. */
  134. public function count()
  135. {
  136. if ($this->count === null) {
  137. $this->rewind();
  138. }
  139. return $this->count;
  140. }
  141. }