1<?php 2 3namespace Elastica; 4 5use Elastica\Query\AbstractQuery; 6use Elastica\Script\AbstractScript; 7use Elastica\Script\Script; 8 9class Reindex extends Param 10{ 11 public const VERSION_TYPE = 'version_type'; 12 public const VERSION_TYPE_INTERNAL = 'internal'; 13 public const VERSION_TYPE_EXTERNAL = 'external'; 14 public const OPERATION_TYPE = 'op_type'; 15 public const OPERATION_TYPE_CREATE = 'create'; 16 public const CONFLICTS = 'conflicts'; 17 public const CONFLICTS_PROCEED = 'proceed'; 18 public const SIZE = 'size'; 19 public const QUERY = 'query'; 20 public const SORT = 'sort'; 21 public const SCRIPT = 'script'; 22 public const SOURCE = '_source'; 23 public const REMOTE = 'remote'; 24 public const SLICE = 'slice'; 25 public const REFRESH = 'refresh'; 26 public const REFRESH_TRUE = 'true'; 27 public const REFRESH_FALSE = 'false'; 28 public const REFRESH_WAIT_FOR = 'wait_for'; 29 public const WAIT_FOR_COMPLETION = 'wait_for_completion'; 30 31 /** 32 * @deprecated since version 7.2.0, use a boolean as parameter instead. 33 */ 34 public const WAIT_FOR_COMPLETION_FALSE = 'false'; 35 public const WAIT_FOR_ACTIVE_SHARDS = 'wait_for_active_shards'; 36 public const TIMEOUT = 'timeout'; 37 public const SCROLL = 'scroll'; 38 public const REQUESTS_PER_SECOND = 'requests_per_second'; 39 public const PIPELINE = 'pipeline'; 40 public const SLICES = 'slices'; 41 public const SLICES_AUTO = 'auto'; 42 43 /** 44 * @var Index 45 */ 46 protected $_oldIndex; 47 48 /** 49 * @var Index 50 */ 51 protected $_newIndex; 52 53 /** 54 * @var Response|null 55 */ 56 protected $_lastResponse; 57 58 public function __construct(Index $oldIndex, Index $newIndex, array $params = []) 59 { 60 $this->_oldIndex = $oldIndex; 61 $this->_newIndex = $newIndex; 62 63 $this->setParams($params); 64 } 65 66 public function run(): Response 67 { 68 $body = $this->_getBody($this->_oldIndex, $this->_newIndex, $this->getParams()); 69 70 $reindexEndpoint = new \Elasticsearch\Endpoints\Reindex(); 71 $params = \array_intersect_key($this->getParams(), \array_fill_keys($reindexEndpoint->getParamWhitelist(), null)); 72 $reindexEndpoint->setParams($params); 73 $reindexEndpoint->setBody($body); 74 75 $this->_lastResponse = $this->_oldIndex->getClient()->requestEndpoint($reindexEndpoint); 76 77 return $this->_lastResponse; 78 } 79 80 /** 81 * @param bool $value 82 */ 83 public function setWaitForCompletion($value): void 84 { 85 if (\is_bool($value)) { 86 $value = $value ? 'true' : 'false'; 87 } else { 88 \trigger_deprecation('ruflin/elastica', '7.2.0', 'Passing anything else than a boolean as 1st argument to "%s()" is deprecated, pass a boolean instead. It will be removed in 8.0.', __METHOD__); 89 } 90 91 $this->setParam(self::WAIT_FOR_COMPLETION, $value); 92 } 93 94 public function setWaitForActiveShards($value): void 95 { 96 $this->setParam(self::WAIT_FOR_ACTIVE_SHARDS, $value); 97 } 98 99 public function setTimeout($value): void 100 { 101 $this->setParam(self::TIMEOUT, $value); 102 } 103 104 public function setScroll($value): void 105 { 106 $this->setParam(self::SCROLL, $value); 107 } 108 109 public function setRequestsPerSecond($value): void 110 { 111 $this->setParam(self::REQUESTS_PER_SECOND, $value); 112 } 113 114 public function setScript(Script $script): void 115 { 116 $this->setParam(self::SCRIPT, $script); 117 } 118 119 public function setQuery(AbstractQuery $query): void 120 { 121 $this->setParam(self::QUERY, $query); 122 } 123 124 public function setPipeline(Pipeline $pipeline): void 125 { 126 $this->setParam(self::PIPELINE, $pipeline); 127 } 128 129 public function setRefresh(string $value): void 130 { 131 $this->setParam(self::REFRESH, $value); 132 } 133 134 public function getTaskId() 135 { 136 $taskId = null; 137 if ($this->_lastResponse instanceof Response) { 138 $taskId = $this->_lastResponse->getData()['task'] ?: null; 139 } 140 141 return $taskId; 142 } 143 144 protected function _getBody(Index $oldIndex, Index $newIndex, array $params): array 145 { 146 $body = \array_merge([ 147 'source' => $this->_getSourcePartBody($oldIndex, $params), 148 'dest' => $this->_getDestPartBody($newIndex, $params), 149 ], $this->_resolveBodyOptions($params)); 150 151 return $this->_setBodyScript($body); 152 } 153 154 protected function _getSourcePartBody(Index $index, array $params): array 155 { 156 $sourceBody = \array_merge([ 157 'index' => $index->getName(), 158 ], $this->_resolveSourceOptions($params)); 159 160 return $this->_setSourceQuery($sourceBody); 161 } 162 163 protected function _getDestPartBody(Index $index, array $params): array 164 { 165 $destBody = \array_merge([ 166 'index' => $index->getName(), 167 ], $this->_resolveDestOptions($params)); 168 169 // Resolves the pipeline name 170 $pipeline = $destBody[self::PIPELINE] ?? null; 171 if ($pipeline instanceof Pipeline) { 172 $destBody[self::PIPELINE] = $pipeline->getId(); 173 } 174 175 return $destBody; 176 } 177 178 private function _resolveSourceOptions(array $params): array 179 { 180 return \array_intersect_key($params, [ 181 self::QUERY => null, 182 self::SORT => null, 183 self::SOURCE => null, 184 self::REMOTE => null, 185 self::SLICE => null, 186 ]); 187 } 188 189 private function _resolveDestOptions(array $params): array 190 { 191 return \array_intersect_key($params, [ 192 self::VERSION_TYPE => null, 193 self::OPERATION_TYPE => null, 194 self::PIPELINE => null, 195 ]); 196 } 197 198 private function _resolveBodyOptions(array $params): array 199 { 200 return \array_intersect_key($params, [ 201 self::SIZE => null, 202 self::CONFLICTS => null, 203 ]); 204 } 205 206 private function _setSourceQuery(array $sourceBody): array 207 { 208 if (isset($sourceBody[self::QUERY]) && $sourceBody[self::QUERY] instanceof AbstractQuery) { 209 $sourceBody[self::QUERY] = $sourceBody[self::QUERY]->toArray(); 210 } 211 212 return $sourceBody; 213 } 214 215 private function _setBodyScript(array $body): array 216 { 217 if (!$this->hasParam(self::SCRIPT)) { 218 return $body; 219 } 220 221 $script = $this->getParam(self::SCRIPT); 222 223 if ($script instanceof AbstractScript) { 224 $body = \array_merge($body, $script->toArray()); 225 } else { 226 $body[self::SCRIPT] = $script; 227 } 228 229 return $body; 230 } 231} 232