These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Elastica; |
||
4 | |||
5 | /** |
||
6 | * Scroll Iterator. |
||
7 | * |
||
8 | * @author Manuel Andreo Garcia <[email protected]> |
||
9 | * |
||
10 | * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-scroll.html |
||
11 | */ |
||
12 | class Scroll implements \Iterator |
||
13 | { |
||
14 | /** |
||
15 | * @var string |
||
16 | */ |
||
17 | public $expiryTime; |
||
18 | |||
19 | /** |
||
20 | * @var Search |
||
21 | */ |
||
22 | protected $_search; |
||
23 | |||
24 | /** |
||
25 | * @var string|null |
||
26 | */ |
||
27 | protected $_nextScrollId; |
||
28 | |||
29 | /** |
||
30 | * @var ResultSet|null |
||
31 | */ |
||
32 | protected $_currentResultSet; |
||
33 | |||
34 | /** |
||
35 | * 0: scroll<br> |
||
36 | * 1: scroll id. |
||
37 | * |
||
38 | * @var array |
||
39 | */ |
||
40 | protected $_options = [null, null]; |
||
41 | |||
42 | private $totalPages = 0; |
||
43 | private $currentPage = 0; |
||
44 | |||
45 | /** |
||
46 | * Constructor. |
||
47 | * |
||
48 | * @param Search $search |
||
49 | * @param string $expiryTime |
||
50 | */ |
||
51 | public function __construct(Search $search, $expiryTime = '1m') |
||
52 | { |
||
53 | $this->_search = $search; |
||
54 | $this->expiryTime = $expiryTime; |
||
55 | } |
||
56 | |||
57 | /** |
||
58 | * Returns current result set. |
||
59 | * |
||
60 | * @see http://php.net/manual/en/iterator.current.php |
||
61 | * |
||
62 | * @return ResultSet |
||
63 | */ |
||
64 | public function current() |
||
65 | { |
||
66 | return $this->_currentResultSet; |
||
67 | } |
||
68 | |||
69 | /** |
||
70 | * Next scroll search. |
||
71 | * |
||
72 | * @see http://php.net/manual/en/iterator.next.php |
||
73 | */ |
||
74 | public function next() |
||
75 | { |
||
76 | if ($this->currentPage < $this->totalPages) { |
||
77 | $this->_saveOptions(); |
||
78 | |||
79 | $this->_search->setOption(Search::OPTION_SCROLL, $this->expiryTime); |
||
80 | $this->_search->setOption(Search::OPTION_SCROLL_ID, $this->_nextScrollId); |
||
81 | |||
82 | $this->_setScrollId($this->_search->search()); |
||
83 | |||
84 | $this->_revertOptions(); |
||
85 | } else { |
||
86 | // If there are no pages left, we do not need to query ES. |
||
87 | $this->clear(); |
||
88 | } |
||
89 | } |
||
90 | |||
91 | /** |
||
92 | * Returns scroll id. |
||
93 | * |
||
94 | * @see http://php.net/manual/en/iterator.key.php |
||
95 | * |
||
96 | * @return string |
||
97 | */ |
||
98 | public function key() |
||
99 | { |
||
100 | return $this->_nextScrollId; |
||
101 | } |
||
102 | |||
103 | /** |
||
104 | * Returns true if current result set contains at least one hit. |
||
105 | * |
||
106 | * @see http://php.net/manual/en/iterator.valid.php |
||
107 | * |
||
108 | * @return bool |
||
109 | */ |
||
110 | public function valid() |
||
111 | { |
||
112 | return null !== $this->_nextScrollId; |
||
113 | } |
||
114 | |||
115 | /** |
||
116 | * Initial scroll search. |
||
117 | * |
||
118 | * @see http://php.net/manual/en/iterator.rewind.php |
||
119 | */ |
||
120 | public function rewind() |
||
121 | { |
||
122 | // reset state |
||
123 | $this->_options = [null, null]; |
||
124 | $this->currentPage = 0; |
||
125 | |||
126 | // initial search |
||
127 | $this->_saveOptions(); |
||
128 | |||
129 | $this->_search->setOption(Search::OPTION_SCROLL, $this->expiryTime); |
||
130 | $this->_search->setOption(Search::OPTION_SCROLL_ID, null); |
||
131 | $this->_setScrollId($this->_search->search()); |
||
132 | |||
133 | $this->_revertOptions(); |
||
134 | } |
||
135 | |||
136 | /** |
||
137 | * Cleares the search context on ES and marks this Scroll instance as finished. |
||
138 | */ |
||
139 | public function clear() |
||
140 | { |
||
141 | if (null !== $this->_nextScrollId) { |
||
142 | $this->_search->getClient()->request( |
||
143 | '_search/scroll', |
||
144 | Request::DELETE, |
||
145 | [Search::OPTION_SCROLL_ID => [$this->_nextScrollId]] |
||
146 | ); |
||
147 | |||
148 | // Reset scroll ID so valid() returns false. |
||
149 | $this->_nextScrollId = null; |
||
150 | $this->_currentResultSet = null; |
||
151 | } |
||
152 | } |
||
153 | |||
154 | /** |
||
155 | * Prepares Scroll for next request. |
||
156 | * |
||
157 | * @param ResultSet $resultSet |
||
158 | */ |
||
159 | protected function _setScrollId(ResultSet $resultSet) |
||
160 | { |
||
161 | if (0 === $this->currentPage) { |
||
162 | $this->totalPages = $resultSet->count() > 0 ? ceil($resultSet->getTotalHits() / $resultSet->count()) : 0; |
||
163 | } |
||
164 | |||
165 | $this->_currentResultSet = $resultSet; |
||
166 | ++$this->currentPage; |
||
167 | $this->_nextScrollId = $resultSet->getResponse()->isOk() && $resultSet->count() > 0 ? $resultSet->getResponse()->getScrollId() : null; |
||
168 | } |
||
169 | |||
170 | /** |
||
171 | * Save all search options manipulated by Scroll. |
||
172 | */ |
||
173 | protected function _saveOptions() |
||
174 | { |
||
175 | View Code Duplication | if ($this->_search->hasOption(Search::OPTION_SCROLL)) { |
|
0 ignored issues
–
show
|
|||
176 | $this->_options[0] = $this->_search->getOption(Search::OPTION_SCROLL); |
||
177 | } |
||
178 | |||
179 | View Code Duplication | if ($this->_search->hasOption(Search::OPTION_SCROLL_ID)) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
180 | $this->_options[1] = $this->_search->getOption(Search::OPTION_SCROLL_ID); |
||
181 | } |
||
182 | } |
||
183 | |||
184 | /** |
||
185 | * Revert search options to previously saved state. |
||
186 | */ |
||
187 | protected function _revertOptions() |
||
188 | { |
||
189 | $this->_search->setOption(Search::OPTION_SCROLL, $this->_options[0]); |
||
190 | $this->_search->setOption(Search::OPTION_SCROLL_ID, $this->_options[1]); |
||
191 | } |
||
192 | } |
||
193 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.