Skip to content

Commit dbfe675

Browse files
committed
added Scroll Iterator
1 parent b226c37 commit dbfe675

File tree

6 files changed

+355
-189
lines changed

6 files changed

+355
-189
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file based on the
77
- Multiple rescore query [#820](https://github.com/ruflin/Elastica/issues/820/)
88
- Support for a custom connection timeout through a connectTimeout parameter. [#841](https://github.com/ruflin/Elastica/issues/841/)
99
- SignificantTerms Aggregation [#847](https://github.com/ruflin/Elastica/issues/847/)
10+
- Scroll Iterator [#842](https://github.com/ruflin/Elastica/issues/842/)
1011

1112

1213
### Improvements

lib/Elastica/ScanAndScroll.php

+29-104
Original file line numberDiff line numberDiff line change
@@ -3,154 +3,79 @@
33
namespace Elastica;
44

55
/**
6-
* scan and scroll object
6+
* Scan and Scroll Iterator
77
*
8-
* @category Xodoa
9-
* @package Elastica
108
* @author Manuel Andreo Garcia <[email protected]>
9+
*
1110
* @link http://www.elastic.co/guide/en/elasticsearch/guide/current/scan-scroll.html
1211
*/
13-
class ScanAndScroll implements \Iterator
12+
class ScanAndScroll extends Scroll
1413
{
15-
/**
16-
* time value parameter
17-
*
18-
* @var string
19-
*/
20-
public $expiryTime;
21-
2214
/**
2315
* @var int
2416
*/
2517
public $sizePerShard;
2618

2719
/**
28-
* @var Search
29-
*/
30-
protected $_search;
31-
32-
/**
33-
* @var null|string
34-
*/
35-
protected $_nextScrollId = null;
36-
37-
/**
38-
* @var null|string
39-
*/
40-
protected $_lastScrollId = null;
41-
42-
/**
43-
* @var null|ResultSet
44-
*/
45-
protected $_currentResultSet = null;
46-
47-
/**
48-
* Constructs scroll iterator object
20+
* Constructor
4921
*
5022
* @param Search $search
5123
* @param string $expiryTime
5224
* @param int $sizePerShard
5325
*/
5426
public function __construct(Search $search, $expiryTime = '1m', $sizePerShard = 1000)
5527
{
56-
$this->_search = $search;
57-
$this->expiryTime = $expiryTime;
5828
$this->sizePerShard = $sizePerShard;
59-
}
6029

61-
/**
62-
* Return the current result set
63-
*
64-
* @link http://php.net/manual/en/iterator.current.php
65-
* @return ResultSet
66-
*/
67-
public function current()
68-
{
69-
return $this->_currentResultSet;
30+
parent::__construct($search, $expiryTime);
7031
}
7132

7233
/**
73-
* Perform next scroll search
34+
* Initial scan search
7435
*
75-
* @link http://php.net/manual/en/iterator.next.php
76-
* @return void
77-
*/
78-
public function next()
79-
{
80-
$this->_scroll();
81-
}
82-
83-
/**
84-
* Return the scroll id of current scroll request
85-
*
86-
* @link http://php.net/manual/en/iterator.key.php
87-
* @return string
88-
*/
89-
public function key()
90-
{
91-
return $this->_lastScrollId;
92-
}
93-
94-
/**
95-
* Returns true if current result set contains one hit
96-
*
97-
* @link http://php.net/manual/en/iterator.valid.php
98-
* @return boolean
99-
*/
100-
public function valid()
101-
{
102-
return
103-
$this->_nextScrollId !== null
104-
&& $this->_currentResultSet !== null
105-
&& $this->_currentResultSet->count() > 0;
106-
}
107-
108-
/**
109-
* Start the initial scan search
11036
* @link http://php.net/manual/en/iterator.rewind.php
111-
* @throws \Elastica\Exception\InvalidException
112-
*
113-
* @return void
11437
*/
11538
public function rewind()
11639
{
117-
$this->_search->getQuery()->setSize($this->sizePerShard);
40+
// reset state
41+
$this->_nextScrollId = null;
42+
$this->_options = array(null, null, null, null);
11843

119-
$this->_search->setOption(Search::OPTION_SEARCH_TYPE, Search::OPTION_SEARCH_TYPE_SCAN);
120-
$this->_search->setOption(Search::OPTION_SCROLL, $this->expiryTime);
44+
$this->_saveOptions();
12145

12246
// initial scan request
47+
$this->_search->getQuery()->setSize($this->sizePerShard);
48+
$this->_search->setOption(Search::OPTION_SCROLL, $this->expiryTime);
49+
$this->_search->setOption(Search::OPTION_SCROLL_ID, null);
50+
$this->_search->setOption(Search::OPTION_SEARCH_TYPE, Search::OPTION_SEARCH_TYPE_SCAN);
12351
$this->_setScrollId($this->_search->search());
12452

125-
// trigger first scroll request
126-
$this->_scroll();
53+
$this->_revertOptions();
54+
55+
// first scroll request
56+
$this->next();
12757
}
12858

12959
/**
130-
* Perform next scroll search
131-
* @throws \Elastica\Exception\InvalidException
60+
* Save all search options manipulated by Scroll
13261
*/
133-
protected function _scroll()
62+
protected function _saveOptions()
13463
{
135-
$this->_search->setOption(Search::OPTION_SEARCH_TYPE, Search::OPTION_SEARCH_TYPE_SCROLL);
136-
$this->_search->setOption(Search::OPTION_SCROLL_ID, $this->_nextScrollId);
64+
$query = $this->_search->getQuery();
65+
if ($query->hasParam('size')) {
66+
$this->_options[3] = $query->getParam('size');
67+
}
13768

138-
$resultSet = $this->_search->search();
139-
$this->_currentResultSet = $resultSet;
140-
$this->_setScrollId($resultSet);
69+
parent::_saveOptions();
14170
}
14271

14372
/**
144-
* Save last scroll id and extract the new one if possible
145-
* @param ResultSet $resultSet
73+
* Revert search options to previously saved state
14674
*/
147-
protected function _setScrollId(ResultSet $resultSet)
75+
protected function _revertOptions()
14876
{
149-
$this->_lastScrollId = $this->_nextScrollId;
77+
$this->_search->getQuery()->setSize($this->_options[3]);
15078

151-
$this->_nextScrollId = null;
152-
if ($resultSet->getResponse()->isOk()) {
153-
$this->_nextScrollId = $resultSet->getResponse()->getScrollId();
154-
}
79+
parent::_revertOptions();
15580
}
15681
}

lib/Elastica/Scroll.php

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
<?php
2+
3+
namespace Elastica;
4+
5+
/**
6+
* Scroll Iterator
7+
*
8+
* @author Manuel Andreo Garcia <[email protected]>
9+
*
10+
* @link http://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 null|string
26+
*/
27+
protected $_nextScrollId = null;
28+
29+
/**
30+
* @var null|ResultSet
31+
*/
32+
protected $_currentResultSet = null;
33+
34+
/**
35+
* 0: scroll<br>
36+
* 1: scroll id<br>
37+
* 2: search type.
38+
*
39+
* @var array
40+
*/
41+
protected $_options = array(null, null, null);
42+
43+
/**
44+
* Constructor
45+
*
46+
* @param Search $search
47+
* @param string $expiryTime
48+
*/
49+
public function __construct(Search $search, $expiryTime = '1m')
50+
{
51+
$this->_search = $search;
52+
$this->expiryTime = $expiryTime;
53+
}
54+
55+
/**
56+
* Returns current result set
57+
*
58+
* @link http://php.net/manual/en/iterator.current.php
59+
*
60+
* @return ResultSet
61+
*/
62+
public function current()
63+
{
64+
return $this->_currentResultSet;
65+
}
66+
67+
/**
68+
* Next scroll search
69+
*
70+
* @link http://php.net/manual/en/iterator.next.php
71+
*/
72+
public function next()
73+
{
74+
$this->_saveOptions();
75+
76+
$this->_search->setOption(Search::OPTION_SCROLL, $this->expiryTime);
77+
$this->_search->setOption(Search::OPTION_SCROLL_ID, $this->_nextScrollId);
78+
$this->_search->setOption(Search::OPTION_SEARCH_TYPE, Search::OPTION_SEARCH_TYPE_SCROLL);
79+
$this->_setScrollId($this->_search->search());
80+
81+
$this->_revertOptions();
82+
}
83+
84+
/**
85+
* Returns scroll id
86+
*
87+
* @link http://php.net/manual/en/iterator.key.php
88+
*
89+
* @return string
90+
*/
91+
public function key()
92+
{
93+
return $this->_nextScrollId;
94+
}
95+
96+
/**
97+
* Returns true if current result set contains at least one hit
98+
*
99+
* @link http://php.net/manual/en/iterator.valid.php
100+
*
101+
* @return bool
102+
*/
103+
public function valid()
104+
{
105+
return
106+
$this->_nextScrollId !== null
107+
&& $this->_currentResultSet !== null
108+
&& $this->_currentResultSet->count() > 0;
109+
}
110+
111+
/**
112+
* Initial scroll search
113+
*
114+
* @link http://php.net/manual/en/iterator.rewind.php
115+
*/
116+
public function rewind()
117+
{
118+
// reset state
119+
$this->_nextScrollId = null;
120+
$this->_options = array(null, null, null);
121+
122+
// initial search
123+
$this->_saveOptions();
124+
125+
$this->_search->setOption(Search::OPTION_SCROLL, $this->expiryTime);
126+
$this->_search->setOption(Search::OPTION_SCROLL_ID, null);
127+
$this->_search->setOption(Search::OPTION_SEARCH_TYPE, null);
128+
$this->_setScrollId($this->_search->search());
129+
130+
$this->_revertOptions();
131+
}
132+
133+
/**
134+
* Prepares Scroll for next request
135+
*
136+
* @param ResultSet $resultSet
137+
*/
138+
protected function _setScrollId(ResultSet $resultSet)
139+
{
140+
$this->_currentResultSet = $resultSet;
141+
142+
$this->_nextScrollId = null;
143+
if ($resultSet->getResponse()->isOk()) {
144+
$this->_nextScrollId = $resultSet->getResponse()->getScrollId();
145+
}
146+
}
147+
148+
/**
149+
* Save all search options manipulated by Scroll
150+
*/
151+
protected function _saveOptions()
152+
{
153+
if ($this->_search->hasOption(Search::OPTION_SCROLL)) {
154+
$this->_options[0] = $this->_search->getOption(Search::OPTION_SCROLL);
155+
}
156+
157+
if ($this->_search->hasOption(Search::OPTION_SCROLL_ID)) {
158+
$this->_options[1] = $this->_search->getOption(Search::OPTION_SCROLL_ID);
159+
}
160+
161+
if ($this->_search->hasOption(Search::OPTION_SEARCH_TYPE)) {
162+
$this->_options[2] = $this->_search->getOption(Search::OPTION_SEARCH_TYPE);
163+
}
164+
}
165+
166+
/**
167+
* Revert search options to previously saved state
168+
*/
169+
protected function _revertOptions()
170+
{
171+
$this->_search->setOption(Search::OPTION_SCROLL, $this->_options[0]);
172+
$this->_search->setOption(Search::OPTION_SCROLL_ID, $this->_options[1]);
173+
$this->_search->setOption(Search::OPTION_SEARCH_TYPE, $this->_options[2]);
174+
}
175+
}

lib/Elastica/Search.php

+12
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,18 @@ public function setSuggest(Suggest $suggest)
506506
return $this->setOptionsAndQuery(array(self::OPTION_SEARCH_TYPE_SUGGEST => 'suggest'), $suggest);
507507
}
508508

509+
/**
510+
* Returns the Scroll Iterator
511+
*
512+
* @see Elastica\Scroll
513+
* @param string $expiryTime
514+
* @return Scroll
515+
*/
516+
public function scroll($expiryTime = '1m')
517+
{
518+
return new Scroll($this, $expiryTime);
519+
}
520+
509521
/**
510522
* Returns the ScanAndScroll Iterator
511523
*

0 commit comments

Comments
 (0)