request($method, $path, $document)->json(); } /** * @param string $index Имя индекса * @param string $id ID документа * @return array|null null, если документ не найден (404) * @throws \JsonException */ public function get(string $index, string $id): ?array { $response = $this->request('GET', "/$index/_doc/" . rawurlencode($id)); return $response->status() === 404 ? null : $response->json(); } /** * @param string $index Имя индекса * @param string $id ID документа * @return bool */ public function exists(string $index, string $id): bool { return $this->request('GET', "/$index/_doc/" . rawurlencode($id))->status() === 200; } /** * @param string $index Имя индекса * @param array $query Elasticsearch Query DSL, например ['query' => ['match' => ['title' => 'foo']]] * @return array Ответ Elasticsearch (декодированный JSON) * @throws \JsonException */ public function search(string $index, array $query): array { return $this->request('POST', "/$index/_search", $query)->json(); } /** * @param string $index Имя индекса * @param string $id ID документа * @return bool true, если удалён */ public function delete(string $index, string $id): bool { return $this->request('DELETE', "/$index/_doc/" . rawurlencode($id))->isSuccess(); } /** * @param string $index Имя индекса * @param array $body settings/mappings (опционально) * @return array Ответ Elasticsearch (декодированный JSON) * @throws \JsonException */ public function createIndex(string $index, array $body = []): array { return $this->request('PUT', "/$index", $body ?: null)->json(); } /** * @param string $index Имя индекса * @return bool true, если удалён */ public function deleteIndex(string $index): bool { return $this->request('DELETE', "/$index")->isSuccess(); } /** * Проверяет доступность кластера. Не бросает исключение при недоступности — просто false * (удобно для graceful skip в тестах/коде, когда Elasticsearch может быть не поднят). * * @return bool */ public function ping(): bool { try { return $this->request('GET', '/')->isSuccess(); } catch (RuntimeException) { return false; } } /** * @param string $method HTTP-метод * @param string $path Путь относительно base_url * @param array|null $body Тело запроса (JSON), null — без тела * @return Response */ protected function request(string $method, string $path, ?array $body = null): Response { $http_request = HttpRequest::factory(rtrim($this->config['base_url'] ?? '', '/') . $path) ->method($method) ->timeout($this->config['timeout'] ?? 10); if ($body !== null) { $http_request->json($body); } if (!empty($this->config['username'])) { $http_request->header( 'Authorization', 'Basic ' . base64_encode($this->config['username'] . ':' . ($this->config['password'] ?? '')) ); } return (new Curl())->execute($http_request); } }