1+ <?php
2+ /**
3+ * Elasticsearch PHP Client
4+ *
5+ * @link https://github.com/elastic/elasticsearch-php
6+ * @copyright Copyright (c) Elasticsearch B.V (https://www.elastic.co)
7+ * @license https://opensource.org/licenses/MIT MIT License
8+ *
9+ * Licensed to Elasticsearch B.V under one or more agreements.
10+ * Elasticsearch B.V licenses this file to you under the MIT License.
11+ * See the LICENSE file in the project root for more information.
12+ */
13+ declare (strict_types = 1 );
14+
15+ namespace Elastic \Elasticsearch \Helper \Iterators ;
16+
17+ use Elastic \Elasticsearch \ClientInterface ;
18+ use Elastic \Elasticsearch \Exception \ClientResponseException ;
19+ use Elastic \Elasticsearch \Exception \ServerResponseException ;
20+ use Iterator ;
21+
22+ class SearchResponseIterator implements Iterator
23+ {
24+
25+ /**
26+ * @var ClientInterface
27+ */
28+ private ClientInterface $ client ;
29+
30+ /**
31+ * @var array
32+ */
33+ private array $ params ;
34+
35+ /**
36+ * @var int
37+ */
38+ private int $ currentKey = 0 ;
39+
40+ /**
41+ * @var array
42+ */
43+ private array $ currentScrolledResponse ;
44+
45+ /**
46+ * @var string|null
47+ */
48+ private ?string $ scrollId ;
49+
50+ /**
51+ * @var string duration
52+ */
53+ private $ scrollTtl ;
54+
55+ /**
56+ * Constructor
57+ *
58+ * @param ClientInterface $client
59+ * @param array $searchParams Associative array of parameters
60+ * @see ClientInterface::search()
61+ */
62+ public function __construct (ClientInterface $ client , array $ searchParams )
63+ {
64+ $ this ->client = $ client ;
65+ $ this ->params = $ searchParams ;
66+
67+ if (isset ($ searchParams ['scroll ' ])) {
68+ $ this ->scrollTtl = $ searchParams ['scroll ' ];
69+ }
70+ }
71+
72+ /**
73+ * Destructor
74+ *
75+ * @throws ClientResponseException
76+ * @throws ServerResponseException
77+ */
78+ public function __destruct ()
79+ {
80+ $ this ->clearScroll ();
81+ }
82+
83+ /**
84+ * Sets the time to live duration of a scroll window
85+ *
86+ * @param string $timeToLive
87+ * @return $this
88+ */
89+ public function setScrollTimeout (string $ timeToLive ): SearchResponseIterator
90+ {
91+ $ this ->scrollTtl = $ timeToLive ;
92+ return $ this ;
93+ }
94+
95+ /**
96+ * Clears the current scroll window if there is a scroll_id stored
97+ *
98+ * @return void
99+ * @throws ClientResponseException
100+ * @throws ServerResponseException
101+ */
102+ private function clearScroll (): void
103+ {
104+ if (!empty ($ this ->scrollId )) {
105+ /* @phpstan-ignore-next-line */
106+ $ this ->client ->clearScroll (
107+ [
108+ 'body ' => [
109+ 'scroll_id ' => $ this ->scrollId
110+ ],
111+ 'client ' => [
112+ 'ignore ' => 404
113+ ]
114+ ]
115+ );
116+ $ this ->scrollId = null ;
117+ }
118+ }
119+
120+ /**
121+ * Rewinds the iterator by performing the initial search.
122+ *
123+ * @return void
124+ * @throws ClientResponseException
125+ * @throws ServerResponseException
126+ * @see Iterator::rewind()
127+ */
128+ public function rewind (): void
129+ {
130+ $ this ->clearScroll ();
131+ $ this ->currentKey = 0 ;
132+ /* @phpstan-ignore-next-line */
133+ $ this ->currentScrolledResponse = $ this ->client ->search ($ this ->params )->asArray ();
134+ $ this ->scrollId = $ this ->currentScrolledResponse ['_scroll_id ' ];
135+ }
136+
137+ /**
138+ * Fetches every "page" after the first one using the lastest "scroll_id"
139+ *
140+ * @return void
141+ * @throws ClientResponseException
142+ * @throws ServerResponseException
143+ * @see Iterator::next()
144+ */
145+ public function next (): void
146+ {
147+ /* @phpstan-ignore-next-line */
148+ $ this ->currentScrolledResponse = $ this ->client ->scroll (
149+ [
150+ 'body ' => [
151+ 'scroll_id ' => $ this ->scrollId ,
152+ 'scroll ' => $ this ->scrollTtl
153+ ]
154+ ]
155+ )->asArray ();
156+ $ this ->scrollId = $ this ->currentScrolledResponse ['_scroll_id ' ];
157+ $ this ->currentKey ++;
158+ }
159+
160+ /**
161+ * Returns a boolean value indicating if the current page is valid or not
162+ *
163+ * @return bool
164+ * @see Iterator::valid()
165+ */
166+ public function valid (): bool
167+ {
168+ return isset ($ this ->currentScrolledResponse ['hits ' ]['hits ' ][0 ]);
169+ }
170+
171+ /**
172+ * Returns the current "page"
173+ *
174+ * @return array
175+ * @see Iterator::current()
176+ */
177+ public function current (): array
178+ {
179+ return $ this ->currentScrolledResponse ;
180+ }
181+
182+ /**
183+ * Returns the current "page number" of the current "page"
184+ *
185+ * @return int
186+ * @see Iterator::key()
187+ */
188+ public function key (): int
189+ {
190+ return $ this ->currentKey ;
191+ }
192+ }
0 commit comments