Client.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  1. <?php
  2. namespace Elastica;
  3. use Elastica\Bulk\Action;
  4. use Elastica\Exception\ConnectionException;
  5. use Elastica\Exception\InvalidException;
  6. use Elastica\Script\AbstractScript;
  7. use Elasticsearch\Endpoints\AbstractEndpoint;
  8. use Elasticsearch\Endpoints\Indices\ForceMerge;
  9. use Elasticsearch\Endpoints\Indices\Refresh;
  10. use Elasticsearch\Endpoints\Update;
  11. use Psr\Log\LoggerInterface;
  12. use Psr\Log\NullLogger;
  13. /**
  14. * Client to connect the the elasticsearch server.
  15. *
  16. * @author Nicolas Ruflin <spam@ruflin.com>
  17. */
  18. class Client
  19. {
  20. /**
  21. * Config with defaults.
  22. *
  23. * log: Set to true, to enable logging, set a string to log to a specific file
  24. * retryOnConflict: Use in \Elastica\Client::updateDocument
  25. * bigintConversion: Set to true to enable the JSON bigint to string conversion option (see issue #717)
  26. *
  27. * @var array
  28. */
  29. protected $_config = [
  30. 'host' => null,
  31. 'port' => null,
  32. 'path' => null,
  33. 'url' => null,
  34. 'proxy' => null,
  35. 'transport' => null,
  36. 'persistent' => true,
  37. 'timeout' => null,
  38. 'connections' => [], // host, port, path, timeout, transport, compression, persistent, timeout, username, password, config -> (curl, headers, url)
  39. 'roundRobin' => false,
  40. 'log' => false,
  41. 'retryOnConflict' => 0,
  42. 'bigintConversion' => false,
  43. 'username' => null,
  44. 'password' => null,
  45. ];
  46. /**
  47. * @var callback
  48. */
  49. protected $_callback;
  50. /**
  51. * @var Connection\ConnectionPool
  52. */
  53. protected $_connectionPool;
  54. /**
  55. * @var \Elastica\Request|null
  56. */
  57. protected $_lastRequest;
  58. /**
  59. * @var \Elastica\Response|null
  60. */
  61. protected $_lastResponse;
  62. /**
  63. * @var LoggerInterface
  64. */
  65. protected $_logger;
  66. /**
  67. * @var string
  68. */
  69. protected $_version;
  70. /**
  71. * Creates a new Elastica client.
  72. *
  73. * @param array $config OPTIONAL Additional config options
  74. * @param callback $callback OPTIONAL Callback function which can be used to be notified about errors (for example connection down)
  75. * @param LoggerInterface $logger
  76. */
  77. public function __construct(array $config = [], $callback = null, LoggerInterface $logger = null)
  78. {
  79. $this->_callback = $callback;
  80. if (!$logger && isset($config['log']) && $config['log']) {
  81. $logger = new Log($config['log']);
  82. }
  83. $this->_logger = $logger ?: new NullLogger();
  84. $this->setConfig($config);
  85. $this->_initConnections();
  86. }
  87. /**
  88. * Get current version.
  89. *
  90. * @return string
  91. */
  92. public function getVersion()
  93. {
  94. if ($this->_version) {
  95. return $this->_version;
  96. }
  97. $data = $this->request('/')->getData();
  98. return $this->_version = $data['version']['number'];
  99. }
  100. /**
  101. * Inits the client connections.
  102. */
  103. protected function _initConnections()
  104. {
  105. $connections = [];
  106. foreach ($this->getConfig('connections') as $connection) {
  107. $connections[] = Connection::create($this->_prepareConnectionParams($connection));
  108. }
  109. if (isset($this->_config['servers'])) {
  110. foreach ($this->getConfig('servers') as $server) {
  111. $connections[] = Connection::create($this->_prepareConnectionParams($server));
  112. }
  113. }
  114. // If no connections set, create default connection
  115. if (empty($connections)) {
  116. $connections[] = Connection::create($this->_prepareConnectionParams($this->getConfig()));
  117. }
  118. if (!isset($this->_config['connectionStrategy'])) {
  119. if (true === $this->getConfig('roundRobin')) {
  120. $this->setConfigValue('connectionStrategy', 'RoundRobin');
  121. } else {
  122. $this->setConfigValue('connectionStrategy', 'Simple');
  123. }
  124. }
  125. $strategy = Connection\Strategy\StrategyFactory::create($this->getConfig('connectionStrategy'));
  126. $this->_connectionPool = new Connection\ConnectionPool($connections, $strategy, $this->_callback);
  127. }
  128. /**
  129. * Creates a Connection params array from a Client or server config array.
  130. *
  131. * @param array $config
  132. *
  133. * @return array
  134. */
  135. protected function _prepareConnectionParams(array $config)
  136. {
  137. $params = [];
  138. $params['config'] = [];
  139. foreach ($config as $key => $value) {
  140. if (in_array($key, ['bigintConversion', 'curl', 'headers', 'url'])) {
  141. $params['config'][$key] = $value;
  142. } else {
  143. $params[$key] = $value;
  144. }
  145. }
  146. return $params;
  147. }
  148. /**
  149. * Sets specific config values (updates and keeps default values).
  150. *
  151. * @param array $config Params
  152. *
  153. * @return $this
  154. */
  155. public function setConfig(array $config)
  156. {
  157. foreach ($config as $key => $value) {
  158. $this->_config[$key] = $value;
  159. }
  160. return $this;
  161. }
  162. /**
  163. * Returns a specific config key or the whole
  164. * config array if not set.
  165. *
  166. * @param string $key Config key
  167. *
  168. * @throws \Elastica\Exception\InvalidException
  169. *
  170. * @return array|string Config value
  171. */
  172. public function getConfig($key = '')
  173. {
  174. if (empty($key)) {
  175. return $this->_config;
  176. }
  177. if (!array_key_exists($key, $this->_config)) {
  178. throw new InvalidException('Config key is not set: '.$key);
  179. }
  180. return $this->_config[$key];
  181. }
  182. /**
  183. * Sets / overwrites a specific config value.
  184. *
  185. * @param string $key Key to set
  186. * @param mixed $value Value
  187. *
  188. * @return $this
  189. */
  190. public function setConfigValue($key, $value)
  191. {
  192. return $this->setConfig([$key => $value]);
  193. }
  194. /**
  195. * @param array|string $keys config key or path of config keys
  196. * @param mixed $default default value will be returned if key was not found
  197. *
  198. * @return mixed
  199. */
  200. public function getConfigValue($keys, $default = null)
  201. {
  202. $value = $this->_config;
  203. foreach ((array) $keys as $key) {
  204. if (isset($value[$key])) {
  205. $value = $value[$key];
  206. } else {
  207. return $default;
  208. }
  209. }
  210. return $value;
  211. }
  212. /**
  213. * Returns the index for the given connection.
  214. *
  215. * @param string $name Index name to create connection to
  216. *
  217. * @return \Elastica\Index Index for the given name
  218. */
  219. public function getIndex($name)
  220. {
  221. return new Index($this, $name);
  222. }
  223. /**
  224. * Adds a HTTP Header.
  225. *
  226. * @param string $header The HTTP Header
  227. * @param string $headerValue The HTTP Header Value
  228. *
  229. * @throws \Elastica\Exception\InvalidException If $header or $headerValue is not a string
  230. *
  231. * @return $this
  232. */
  233. public function addHeader($header, $headerValue)
  234. {
  235. if (is_string($header) && is_string($headerValue)) {
  236. $this->_config['headers'][$header] = $headerValue;
  237. } else {
  238. throw new InvalidException('Header must be a string');
  239. }
  240. return $this;
  241. }
  242. /**
  243. * Remove a HTTP Header.
  244. *
  245. * @param string $header The HTTP Header to remove
  246. *
  247. * @throws \Elastica\Exception\InvalidException If $header is not a string
  248. *
  249. * @return $this
  250. */
  251. public function removeHeader($header)
  252. {
  253. if (is_string($header)) {
  254. if (array_key_exists($header, $this->_config['headers'])) {
  255. unset($this->_config['headers'][$header]);
  256. }
  257. } else {
  258. throw new InvalidException('Header must be a string');
  259. }
  260. return $this;
  261. }
  262. /**
  263. * Uses _bulk to send documents to the server.
  264. *
  265. * Array of \Elastica\Document as input. Index and type has to be
  266. * set inside the document, because for bulk settings documents,
  267. * documents can belong to any type and index
  268. *
  269. * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
  270. *
  271. * @param array|\Elastica\Document[] $docs Array of Elastica\Document
  272. * @param array $requestParams
  273. *
  274. * @throws \Elastica\Exception\InvalidException If docs is empty
  275. *
  276. * @return \Elastica\Bulk\ResponseSet Response object
  277. */
  278. public function updateDocuments(array $docs, array $requestParams = [])
  279. {
  280. if (empty($docs)) {
  281. throw new InvalidException('Array has to consist of at least one element');
  282. }
  283. $bulk = new Bulk($this);
  284. $bulk->addDocuments($docs, Action::OP_TYPE_UPDATE);
  285. foreach ($requestParams as $key => $value) {
  286. $bulk->setRequestParam($key, $value);
  287. }
  288. return $bulk->send();
  289. }
  290. /**
  291. * Uses _bulk to send documents to the server.
  292. *
  293. * Array of \Elastica\Document as input. Index and type has to be
  294. * set inside the document, because for bulk settings documents,
  295. * documents can belong to any type and index
  296. *
  297. * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
  298. *
  299. * @param array|\Elastica\Document[] $docs Array of Elastica\Document
  300. * @param array $requestParams
  301. *
  302. * @throws \Elastica\Exception\InvalidException If docs is empty
  303. *
  304. * @return \Elastica\Bulk\ResponseSet Response object
  305. */
  306. public function addDocuments(array $docs, array $requestParams = [])
  307. {
  308. if (empty($docs)) {
  309. throw new InvalidException('Array has to consist of at least one element');
  310. }
  311. $bulk = new Bulk($this);
  312. $bulk->addDocuments($docs);
  313. foreach ($requestParams as $key => $value) {
  314. $bulk->setRequestParam($key, $value);
  315. }
  316. return $bulk->send();
  317. }
  318. /**
  319. * Update document, using update script. Requires elasticsearch >= 0.19.0.
  320. *
  321. * @param int|string $id document id
  322. * @param array|\Elastica\Script\AbstractScript|\Elastica\Document $data raw data for request body
  323. * @param string $index index to update
  324. * @param string $type type of index to update
  325. * @param array $options array of query params to use for query. For possible options check es api
  326. *
  327. * @return \Elastica\Response
  328. *
  329. * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html
  330. */
  331. public function updateDocument($id, $data, $index, $type, array $options = [])
  332. {
  333. $endpoint = new Update();
  334. $endpoint->setID($id);
  335. $endpoint->setIndex($index);
  336. $endpoint->setType($type);
  337. if ($data instanceof AbstractScript) {
  338. $requestData = $data->toArray();
  339. } elseif ($data instanceof Document) {
  340. $requestData = ['doc' => $data->getData()];
  341. if ($data->getDocAsUpsert()) {
  342. $requestData['doc_as_upsert'] = true;
  343. }
  344. $docOptions = $data->getOptions(
  345. [
  346. 'version',
  347. 'version_type',
  348. 'routing',
  349. 'percolate',
  350. 'parent',
  351. 'fields',
  352. 'retry_on_conflict',
  353. 'consistency',
  354. 'replication',
  355. 'refresh',
  356. 'timeout',
  357. ]
  358. );
  359. $options += $docOptions;
  360. // set fields param to source only if options was not set before
  361. if ($data instanceof Document && ($data->isAutoPopulate()
  362. || $this->getConfigValue(['document', 'autoPopulate'], false))
  363. && !isset($options['fields'])
  364. ) {
  365. $options['fields'] = '_source';
  366. }
  367. } else {
  368. $requestData = $data;
  369. }
  370. //If an upsert document exists
  371. if ($data instanceof AbstractScript || $data instanceof Document) {
  372. if ($data->hasUpsert()) {
  373. $requestData['upsert'] = $data->getUpsert()->getData();
  374. }
  375. }
  376. if (!isset($options['retry_on_conflict'])) {
  377. if ($retryOnConflict = $this->getConfig('retryOnConflict')) {
  378. $options['retry_on_conflict'] = $retryOnConflict;
  379. }
  380. }
  381. $endpoint->setBody($requestData);
  382. $endpoint->setParams($options);
  383. $response = $this->requestEndpoint($endpoint);
  384. if ($response->isOk()
  385. && $data instanceof Document
  386. && ($data->isAutoPopulate() || $this->getConfigValue(['document', 'autoPopulate'], false))
  387. ) {
  388. $responseData = $response->getData();
  389. if (isset($responseData['_version'])) {
  390. $data->setVersion($responseData['_version']);
  391. }
  392. if (isset($options['fields'])) {
  393. $this->_populateDocumentFieldsFromResponse($response, $data, $options['fields']);
  394. }
  395. }
  396. return $response;
  397. }
  398. /**
  399. * @param \Elastica\Response $response
  400. * @param \Elastica\Document $document
  401. * @param string $fields Array of field names to be populated or '_source' if whole document data should be updated
  402. */
  403. protected function _populateDocumentFieldsFromResponse(Response $response, Document $document, $fields)
  404. {
  405. $responseData = $response->getData();
  406. if ('_source' == $fields) {
  407. if (isset($responseData['get']['_source']) && is_array($responseData['get']['_source'])) {
  408. $document->setData($responseData['get']['_source']);
  409. }
  410. } else {
  411. $keys = explode(',', $fields);
  412. $data = $document->getData();
  413. foreach ($keys as $key) {
  414. if (isset($responseData['get']['fields'][$key])) {
  415. $data[$key] = $responseData['get']['fields'][$key];
  416. } elseif (isset($data[$key])) {
  417. unset($data[$key]);
  418. }
  419. }
  420. $document->setData($data);
  421. }
  422. }
  423. /**
  424. * Bulk deletes documents.
  425. *
  426. * @param array|\Elastica\Document[] $docs
  427. * @param array $requestParams
  428. *
  429. * @throws \Elastica\Exception\InvalidException
  430. *
  431. * @return \Elastica\Bulk\ResponseSet
  432. */
  433. public function deleteDocuments(array $docs, array $requestParams = [])
  434. {
  435. if (empty($docs)) {
  436. throw new InvalidException('Array has to consist of at least one element');
  437. }
  438. $bulk = new Bulk($this);
  439. $bulk->addDocuments($docs, Action::OP_TYPE_DELETE);
  440. foreach ($requestParams as $key => $value) {
  441. $bulk->setRequestParam($key, $value);
  442. }
  443. return $bulk->send();
  444. }
  445. /**
  446. * Returns the status object for all indices.
  447. *
  448. * @return \Elastica\Status Status object
  449. */
  450. public function getStatus()
  451. {
  452. return new Status($this);
  453. }
  454. /**
  455. * Returns the current cluster.
  456. *
  457. * @return \Elastica\Cluster Cluster object
  458. */
  459. public function getCluster()
  460. {
  461. return new Cluster($this);
  462. }
  463. /**
  464. * Establishes the client connections.
  465. */
  466. public function connect()
  467. {
  468. return $this->_initConnections();
  469. }
  470. /**
  471. * @param \Elastica\Connection $connection
  472. *
  473. * @return $this
  474. */
  475. public function addConnection(Connection $connection)
  476. {
  477. $this->_connectionPool->addConnection($connection);
  478. return $this;
  479. }
  480. /**
  481. * Determines whether a valid connection is available for use.
  482. *
  483. * @return bool
  484. */
  485. public function hasConnection()
  486. {
  487. return $this->_connectionPool->hasConnection();
  488. }
  489. /**
  490. * @throws \Elastica\Exception\ClientException
  491. *
  492. * @return \Elastica\Connection
  493. */
  494. public function getConnection()
  495. {
  496. return $this->_connectionPool->getConnection();
  497. }
  498. /**
  499. * @return \Elastica\Connection[]
  500. */
  501. public function getConnections()
  502. {
  503. return $this->_connectionPool->getConnections();
  504. }
  505. /**
  506. * @return \Elastica\Connection\Strategy\StrategyInterface
  507. */
  508. public function getConnectionStrategy()
  509. {
  510. return $this->_connectionPool->getStrategy();
  511. }
  512. /**
  513. * @param array|\Elastica\Connection[] $connections
  514. *
  515. * @return $this
  516. */
  517. public function setConnections(array $connections)
  518. {
  519. $this->_connectionPool->setConnections($connections);
  520. return $this;
  521. }
  522. /**
  523. * Deletes documents with the given ids, index, type from the index.
  524. *
  525. * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
  526. *
  527. * @param array $ids Document ids
  528. * @param string|\Elastica\Index $index Index name
  529. * @param string|\Elastica\Type $type Type of documents
  530. * @param string|bool $routing Optional routing key for all ids
  531. *
  532. * @throws \Elastica\Exception\InvalidException
  533. *
  534. * @return \Elastica\Bulk\ResponseSet Response object
  535. */
  536. public function deleteIds(array $ids, $index, $type, $routing = false)
  537. {
  538. if (empty($ids)) {
  539. throw new InvalidException('Array has to consist of at least one id');
  540. }
  541. $bulk = new Bulk($this);
  542. $bulk->setIndex($index);
  543. $bulk->setType($type);
  544. foreach ($ids as $id) {
  545. $action = new Action(Action::OP_TYPE_DELETE);
  546. $action->setId($id);
  547. if (!empty($routing)) {
  548. $action->setRouting($routing);
  549. }
  550. $bulk->addAction($action);
  551. }
  552. return $bulk->send();
  553. }
  554. /**
  555. * Bulk operation.
  556. *
  557. * Every entry in the params array has to exactly on array
  558. * of the bulk operation. An example param array would be:
  559. *
  560. * array(
  561. * array('index' => array('_index' => 'test', '_type' => 'user', '_id' => '1')),
  562. * array('user' => array('name' => 'hans')),
  563. * array('delete' => array('_index' => 'test', '_type' => 'user', '_id' => '2'))
  564. * );
  565. *
  566. * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
  567. *
  568. * @param array $params Parameter array
  569. *
  570. * @throws \Elastica\Exception\ResponseException
  571. * @throws \Elastica\Exception\InvalidException
  572. *
  573. * @return \Elastica\Bulk\ResponseSet Response object
  574. */
  575. public function bulk(array $params)
  576. {
  577. if (empty($params)) {
  578. throw new InvalidException('Array has to consist of at least one param');
  579. }
  580. $bulk = new Bulk($this);
  581. $bulk->addRawData($params);
  582. return $bulk->send();
  583. }
  584. /**
  585. * Makes calls to the elasticsearch server based on this index.
  586. *
  587. * It's possible to make any REST query directly over this method
  588. *
  589. * @param string $path Path to call
  590. * @param string $method Rest method to use (GET, POST, DELETE, PUT)
  591. * @param array|string $data OPTIONAL Arguments as array or pre-encoded string
  592. * @param array $query OPTIONAL Query params
  593. * @param string $contentType Content-Type sent with this request
  594. *
  595. * @throws Exception\ConnectionException|Exception\ClientException
  596. *
  597. * @return Response Response object
  598. */
  599. public function request($path, $method = Request::GET, $data = [], array $query = [], $contentType = Request::DEFAULT_CONTENT_TYPE)
  600. {
  601. $connection = $this->getConnection();
  602. $request = $this->_lastRequest = new Request($path, $method, $data, $query, $connection, $contentType);
  603. $this->_lastResponse = null;
  604. try {
  605. $response = $this->_lastResponse = $request->send();
  606. } catch (ConnectionException $e) {
  607. $this->_connectionPool->onFail($connection, $e, $this);
  608. $this->_log($e);
  609. // In case there is no valid connection left, throw exception which caused the disabling of the connection.
  610. if (!$this->hasConnection()) {
  611. throw $e;
  612. }
  613. return $this->request($path, $method, $data, $query);
  614. }
  615. $this->_log($request);
  616. return $response;
  617. }
  618. /**
  619. * Makes calls to the elasticsearch server with usage official client Endpoint.
  620. *
  621. * @param AbstractEndpoint $endpoint
  622. *
  623. * @return Response
  624. */
  625. public function requestEndpoint(AbstractEndpoint $endpoint)
  626. {
  627. return $this->request(
  628. ltrim($endpoint->getURI(), '/'),
  629. $endpoint->getMethod(),
  630. null === $endpoint->getBody() ? [] : $endpoint->getBody(),
  631. $endpoint->getParams()
  632. );
  633. }
  634. /**
  635. * logging.
  636. *
  637. * @deprecated Overwriting Client->_log is deprecated. Handle logging functionality by using a custom LoggerInterface.
  638. *
  639. * @param mixed $context
  640. */
  641. protected function _log($context)
  642. {
  643. if ($context instanceof ConnectionException) {
  644. $this->_logger->error('Elastica Request Failure', [
  645. 'exception' => $context,
  646. 'request' => $context->getRequest()->toArray(),
  647. 'retry' => $this->hasConnection(),
  648. ]);
  649. return;
  650. }
  651. if ($context instanceof Request) {
  652. $this->_logger->debug('Elastica Request', [
  653. 'request' => $context->toArray(),
  654. 'response' => $this->_lastResponse ? $this->_lastResponse->getData() : null,
  655. 'responseStatus' => $this->_lastResponse ? $this->_lastResponse->getStatus() : null,
  656. ]);
  657. return;
  658. }
  659. $this->_logger->debug('Elastica Request', [
  660. 'message' => $context,
  661. ]);
  662. }
  663. /**
  664. * Optimizes all search indices.
  665. *
  666. * @param array $args OPTIONAL Optional arguments
  667. *
  668. * @return \Elastica\Response Response object
  669. *
  670. * @deprecated Replaced by forcemergeAll
  671. * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-optimize.html
  672. */
  673. public function optimizeAll($args = [])
  674. {
  675. trigger_error('Deprecated: Elastica\Client::optimizeAll() is deprecated and will be removed in further Elastica releases. Use Elastica\Client::forcemergeAll() instead.', E_USER_DEPRECATED);
  676. return $this->forcemergeAll($args);
  677. }
  678. /**
  679. * Force merges all search indices.
  680. *
  681. * @param array $args OPTIONAL Optional arguments
  682. *
  683. * @return \Elastica\Response Response object
  684. *
  685. * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html
  686. */
  687. public function forcemergeAll($args = [])
  688. {
  689. $endpoint = new ForceMerge();
  690. $endpoint->setParams($args);
  691. return $this->requestEndpoint($endpoint);
  692. }
  693. /**
  694. * Refreshes all search indices.
  695. *
  696. * @return \Elastica\Response Response object
  697. *
  698. * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-refresh.html
  699. */
  700. public function refreshAll()
  701. {
  702. return $this->requestEndpoint(new Refresh());
  703. }
  704. /**
  705. * @return Request|null
  706. */
  707. public function getLastRequest()
  708. {
  709. return $this->_lastRequest;
  710. }
  711. /**
  712. * @return Response|null
  713. */
  714. public function getLastResponse()
  715. {
  716. return $this->_lastResponse;
  717. }
  718. /**
  719. * Replace the existing logger.
  720. *
  721. * @param LoggerInterface $logger
  722. *
  723. * @return $this
  724. */
  725. public function setLogger(LoggerInterface $logger)
  726. {
  727. $this->_logger = $logger;
  728. return $this;
  729. }
  730. }