Class yii\elasticsearch\Connection
Inheritance | yii\elasticsearch\Connection » yii\base\Component |
---|---|
Available since extension's version | 2.0 |
Source Code | https://github.com/yiisoft/yii2-elasticsearch/blob/master/Connection.php |
Elasticsearch Connection is used to connect to an Elasticsearch cluster version 0.20 or higher
Public Properties
Property | Type | Description | Defined By |
---|---|---|---|
$activeNode | string | The active node. | yii\elasticsearch\Connection |
$auth | array | Authentication data used to connect to the Elasticsearch node. | yii\elasticsearch\Connection |
$autodetectCluster | boolean | Whether to autodetect available cluster nodes on open() | yii\elasticsearch\Connection |
$connectionTimeout | float | Timeout to use for connecting to an Elasticsearch node. | yii\elasticsearch\Connection |
$curlOptions | array | Additional options used to configure curl session | yii\elasticsearch\Connection |
$dataTimeout | float | Timeout to use when reading the response from an Elasticsearch node. | yii\elasticsearch\Connection |
$defaultProtocol | string | Default protocol to connect to nodes | yii\elasticsearch\Connection |
$driverName | string | Name of the DB driver. | yii\elasticsearch\Connection |
$dslVersion | integer | Version of the domain-specific language to use with the server. | yii\elasticsearch\Connection |
$isActive | boolean | Whether the DB connection is established. | yii\elasticsearch\Connection |
$nodes | array | The Elasticsearch cluster nodes to connect to. | yii\elasticsearch\Connection |
$queryBuilder | yii\elasticsearch\QueryBuilder | yii\elasticsearch\Connection |
Public Methods
Protected Methods
Method | Description | Defined By |
---|---|---|
decodeErrorBody() | Try to decode error information if it is valid json, return it if not. | yii\elasticsearch\Connection |
httpRequest() | Performs HTTP request | yii\elasticsearch\Connection |
initConnection() | Initializes the DB connection. | yii\elasticsearch\Connection |
populateNodes() | Populates $nodes with the result of a cluster nodes request. | yii\elasticsearch\Connection |
selectActiveNode() | Select active node randomly | yii\elasticsearch\Connection |
Events
Event | Type | Description | Defined By |
---|---|---|---|
EVENT_AFTER_OPEN | yii\elasticsearch\Event | An event that is triggered after a DB connection is established | yii\elasticsearch\Connection |
Property Details
Authentication data used to connect to the Elasticsearch node.
Array elements:
username
: the username for authentication.password
: the password for authentication.
Array either MUST contain both username and password on not contain any authentication credentials.
See also https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-authenticate.html.
Whether to autodetect available cluster nodes on open()
Timeout to use for connecting to an Elasticsearch node.
This value will be used to configure the curl CURLOPT_CONNECTTIMEOUT
option.
If not set, no explicit timeout will be set for curl.
Additional options used to configure curl session
Timeout to use when reading the response from an Elasticsearch node.
This value will be used to configure the curl CURLOPT_TIMEOUT
option.
If not set, no explicit timeout will be set for curl.
Default protocol to connect to nodes
Version of the domain-specific language to use with the server.
This must be set to the major version of the Elasticsearch server in use, e.g. 5
for Elasticsearch 5.x.x,
6
for Elasticsearch 6.x.x, and 7
for Elasticsearch 7.x.x.
The Elasticsearch cluster nodes to connect to.
This is populated with the result of a cluster nodes request when $autodetectCluster is true.
Additional special options:
auth
: overrides $auth property. For example:
[
'http_address' => 'inet[/127.0.0.1:9200]',
'auth' => ['username' => 'yiiuser', 'password' => 'yiipw'], // Overrides the `auth` property of the class with specific login and password
//'auth' => ['username' => 'yiiuser', 'password' => 'yiipw'], // Disabled auth regardless of `auth` property of the class
]
protocol
: explicitly sets the protocol for the current node (useful when manually defining a HTTPS cluster)
Method Details
Closes the connection when this component is being serialized.
public array __sleep ( ) |
public function __sleep()
{
$this->close();
return array_keys(get_object_vars($this));
}
Closes the currently active DB connection.
It does nothing if the connection is already closed.
public void close ( ) |
public function close()
{
if ($this->activeNode === null) {
return;
}
Yii::trace('Closing connection to Elasticsearch. Active node was: '
. $this->nodes[$this->activeNode]['http']['publish_address'], __CLASS__);
$this->activeNode = null;
if ($this->_curl) {
curl_close($this->_curl);
$this->_curl = null;
}
}
Creates a bulk command for execution.
public yii\elasticsearch\BulkCommand createBulkCommand ( $config = [] ) | ||
$config | array |
The configuration for the yii\elasticsearch\BulkCommand class |
return | yii\elasticsearch\BulkCommand |
The DB command |
---|
public function createBulkCommand($config = [])
{
$this->open();
$config['db'] = $this;
$command = new BulkCommand($config);
return $command;
}
Creates a command for execution.
public yii\elasticsearch\Command createCommand ( $config = [] ) | ||
$config | array |
The configuration for the Command class |
return | yii\elasticsearch\Command |
The DB command |
---|
public function createCommand($config = [])
{
$this->open();
$config['db'] = $this;
$command = new Command($config);
return $command;
}
Try to decode error information if it is valid json, return it if not.
protected mixed decodeErrorBody ( $body ) | ||
$body |
protected function decodeErrorBody($body)
{
try {
$decoded = Json::decode($body);
if (isset($decoded['error']) && !is_array($decoded['error'])) {
$decoded['error'] = preg_replace('/\b\w+?Exception\[/', "<span style=\"color: red;\">\\0</span>\n ", $decoded['error']);
}
return $decoded;
} catch(InvalidArgumentException $e) {
return $body;
}
}
Performs DELETE HTTP request
public mixed delete ( $url, $options = [], $body = null, $raw = false ) | ||
$url | string|array |
URL |
$options | array |
URL options |
$body | string |
Request body |
$raw | boolean |
If response body contains JSON and should be decoded |
return | mixed |
Response |
---|---|---|
throws | yii\elasticsearch\Exception | |
throws | \yii\base\InvalidConfigException |
public function delete($url, $options = [], $body = null, $raw = false)
{
$this->open();
return $this->httpRequest('DELETE', $this->createUrl($url, $options), $body, $raw);
}
Performs GET HTTP request
public mixed get ( $url, $options = [], $body = null, $raw = false ) | ||
$url | string|array |
URL |
$options | array |
URL options |
$body | string |
Request body |
$raw | boolean |
If response body contains JSON and should be decoded |
return | mixed |
Response |
---|---|---|
throws | yii\elasticsearch\Exception | |
throws | \yii\base\InvalidConfigException |
public function get($url, $options = [], $body = null, $raw = false)
{
$this->open();
return $this->httpRequest('GET', $this->createUrl($url, $options), $body, $raw);
}
public void getClusterState ( ) |
public function getClusterState()
{
return $this->get(['_cluster', 'state']);
}
Returns the name of the DB driver for the current dsn.
public string getDriverName ( ) | ||
return | string |
Name of the DB driver |
---|
public function getDriverName()
{
return 'elasticsearch';
}
Returns a value indicating whether the DB connection is established.
public boolean getIsActive ( ) | ||
return | boolean |
Whether the DB connection is established |
---|
public function getIsActive()
{
return $this->activeNode !== null;
}
Creates new query builder instance
public yii\elasticsearch\QueryBuilder getQueryBuilder ( ) |
public function getQueryBuilder()
{
return new QueryBuilder($this);
}
Performs HEAD HTTP request
public mixed head ( $url, $options = [], $body = null ) | ||
$url | string|array |
URL |
$options | array |
URL options |
$body | string |
Request body |
return | mixed |
Response |
---|---|---|
throws | yii\elasticsearch\Exception | |
throws | \yii\base\InvalidConfigException |
public function head($url, $options = [], $body = null)
{
$this->open();
return $this->httpRequest('HEAD', $this->createUrl($url, $options), $body);
}
Performs HTTP request
protected mixed httpRequest ( $method, $url, $requestBody = null, $raw = false ) | ||
$method | string |
Method name |
$url | string |
URL |
$requestBody | string |
Request body |
$raw | boolean |
If response body contains JSON and should be decoded |
return | mixed |
If request failed |
---|---|---|
throws | yii\elasticsearch\Exception |
if request failed |
throws | \yii\base\InvalidConfigException |
protected function httpRequest($method, $url, $requestBody = null, $raw = false)
{
$method = strtoupper($method);
// response body and headers
$headers = [];
$headersFinished = false;
$body = '';
$options = [
CURLOPT_USERAGENT => 'Yii Framework ' . Yii::getVersion() . ' ' . __CLASS__,
CURLOPT_RETURNTRANSFER => false,
CURLOPT_HEADER => false,
// http://www.php.net/manual/en/function.curl-setopt.php#82418
CURLOPT_HTTPHEADER => [
'Expect:',
'Content-Type: application/json',
],
CURLOPT_WRITEFUNCTION => function ($curl, $data) use (&$body) {
$body .= $data;
return mb_strlen($data, '8bit');
},
CURLOPT_HEADERFUNCTION => function ($curl, $data) use (&$headers, &$headersFinished) {
if ($data === '') {
$headersFinished = true;
} elseif ($headersFinished) {
$headersFinished = false;
}
if (!$headersFinished && ($pos = strpos($data, ':')) !== false) {
$headers[strtolower(substr($data, 0, $pos))] = trim(substr($data, $pos + 1));
}
return mb_strlen($data, '8bit');
},
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_FORBID_REUSE => false,
];
foreach ($this->curlOptions as $key => $value) {
$options[$key] = $value;
}
if (!empty($this->auth) || isset($this->nodes[$this->activeNode]['auth']) && $this->nodes[$this->activeNode]['auth'] !== false) {
$auth = isset($this->nodes[$this->activeNode]['auth']) ? $this->nodes[$this->activeNode]['auth'] : $this->auth;
if (empty($auth['username'])) {
throw new InvalidConfigException('Username is required to use authentication');
}
if (empty($auth['password'])) {
throw new InvalidConfigException('Password is required to use authentication');
}
$options[CURLOPT_HTTPAUTH] = CURLAUTH_BASIC;
$options[CURLOPT_USERPWD] = $auth['username'] . ':' . $auth['password'];
}
if ($this->connectionTimeout !== null) {
$options[CURLOPT_CONNECTTIMEOUT] = $this->connectionTimeout;
}
if ($this->dataTimeout !== null) {
$options[CURLOPT_TIMEOUT] = $this->dataTimeout;
}
if ($requestBody !== null) {
$options[CURLOPT_POSTFIELDS] = $requestBody;
}
if ($method == 'HEAD') {
$options[CURLOPT_NOBODY] = true;
unset($options[CURLOPT_WRITEFUNCTION]);
} else {
$options[CURLOPT_NOBODY] = false;
}
if (is_array($url)) {
list($protocol, $host, $q) = $url;
if (strncmp($host, 'inet[', 5) == 0) {
$host = substr($host, 5, -1);
if (($pos = strpos($host, '/')) !== false) {
$host = substr($host, $pos + 1);
}
}
$profile = "$method $q#$requestBody";
$url = "$protocol://$host/$q";
} else {
$profile = false;
}
Yii::trace("Sending request to Elasticsearch node: $method $url\n$requestBody", __METHOD__);
if ($profile !== false) {
Yii::beginProfile($profile, __METHOD__);
}
$this->resetCurlHandle();
curl_setopt($this->_curl, CURLOPT_URL, $url);
curl_setopt_array($this->_curl, $options);
if (curl_exec($this->_curl) === false) {
throw new Exception('Elasticsearch request failed: ' . curl_errno($this->_curl) . ' - ' . curl_error($this->_curl), [
'requestMethod' => $method,
'requestUrl' => $url,
'requestBody' => $requestBody,
'responseHeaders' => $headers,
'responseBody' => $this->decodeErrorBody($body),
]);
}
$responseCode = curl_getinfo($this->_curl, CURLINFO_HTTP_CODE);
if ($profile !== false) {
Yii::endProfile($profile, __METHOD__);
}
if ($responseCode >= 200 && $responseCode < 300) {
if ($method === 'HEAD') {
return true;
} else {
if (isset($headers['content-length']) && ($len = mb_strlen($body, '8bit')) < $headers['content-length']) {
throw new Exception("Incomplete data received from Elasticsearch: $len < {$headers['content-length']}", [
'requestMethod' => $method,
'requestUrl' => $url,
'requestBody' => $requestBody,
'responseCode' => $responseCode,
'responseHeaders' => $headers,
'responseBody' => $body,
]);
}
if (isset($headers['content-type'])) {
if (!strncmp($headers['content-type'], 'application/json', 16)) {
return $raw ? $body : Json::decode($body);
}
if (!strncmp($headers['content-type'], 'text/plain', 10)) {
return $raw ? $body : array_filter(explode("\n", $body));
}
}
throw new Exception('Unsupported data received from Elasticsearch: ' . $headers['content-type'], [
'requestMethod' => $method,
'requestUrl' => $url,
'requestBody' => $requestBody,
'responseCode' => $responseCode,
'responseHeaders' => $headers,
'responseBody' => $this->decodeErrorBody($body),
]);
}
} elseif ($responseCode == 404) {
return false;
} else {
throw new Exception("Elasticsearch request failed with code $responseCode. Response body:\n{$body}", [
'requestMethod' => $method,
'requestUrl' => $url,
'requestBody' => $requestBody,
'responseCode' => $responseCode,
'responseHeaders' => $headers,
'responseBody' => $this->decodeErrorBody($body),
]);
}
}
public void init ( ) |
public function init()
{
foreach ($this->nodes as &$node) {
if (!isset($node['http_address'])) {
throw new InvalidConfigException('Elasticsearch node needs at least a http_address configured.');
}
if (!isset($node['protocol'])) {
$node['protocol'] = $this->defaultProtocol;
}
if (!in_array($node['protocol'], ['http', 'https'])) {
throw new InvalidConfigException('Valid node protocol settings are "http" and "https".');
}
}
}
Initializes the DB connection.
This method is invoked right after the DB connection is established. The default implementation triggers an EVENT_AFTER_OPEN event.
protected void initConnection ( ) |
protected function initConnection()
{
$this->trigger(self::EVENT_AFTER_OPEN);
}
Establishes a DB connection.
It does nothing if a DB connection has already been established.
public void open ( ) | ||
throws | yii\elasticsearch\Exception |
if connection fails |
---|
public function open()
{
if ($this->activeNode !== null) {
return;
}
if (empty($this->nodes)) {
throw new InvalidConfigException('Elasticsearch needs at least one node to operate.');
}
$this->_curl = curl_init();
if ($this->autodetectCluster) {
$this->populateNodes();
}
$this->selectActiveNode();
Yii::trace('Opening connection to Elasticsearch. Nodes in cluster: ' . count($this->nodes)
. ', active node: ' . $this->nodes[$this->activeNode]['http_address'], __CLASS__);
$this->initConnection();
}
Populates $nodes with the result of a cluster nodes request.
protected void populateNodes ( ) | ||
throws | yii\elasticsearch\Exception |
if no active node(s) found |
---|
protected function populateNodes()
{
$node = reset($this->nodes);
$host = $node['http_address'];
$protocol = isset($node['protocol']) ? $node['protocol'] : $this->defaultProtocol;
if (strncmp($host, 'inet[/', 6) === 0) {
$host = substr($host, 6, -1);
}
$response = $this->httpRequest('GET', "$protocol://$host/_nodes/_all/http");
if (!empty($response['nodes'])) {
$nodes = $response['nodes'];
} else {
$nodes = [];
}
foreach ($nodes as $key => &$node) {
// Make sure that nodes have an 'http_address' property, which is not the case if you're using AWS
// Elasticsearch service (at least as of Oct., 2015). - TO BE VERIFIED
// Temporary workaround - simply ignore all invalid nodes
if (!isset($node['http']['publish_address'])) {
unset($nodes[$key]);
}
$node['http_address'] = $node['http']['publish_address'];
// Protocol is not a standard ES node property, so we add it manually
$node['protocol'] = $this->defaultProtocol;
}
if (!empty($nodes)) {
$this->nodes = array_values($nodes);
} else {
curl_close($this->_curl);
throw new Exception('Cluster autodetection did not find any active node. Make sure a GET /_nodes reguest on the hosts defined in the config returns the "http_address" field for each node.');
}
}
Performs POST HTTP request
public mixed post ( $url, $options = [], $body = null, $raw = false ) | ||
$url | string|array |
URL |
$options | array |
URL options |
$body | string |
Request body |
$raw | boolean |
If response body contains JSON and should be decoded |
return | mixed |
Response |
---|---|---|
throws | yii\elasticsearch\Exception | |
throws | \yii\base\InvalidConfigException |
public function post($url, $options = [], $body = null, $raw = false)
{
$this->open();
return $this->httpRequest('POST', $this->createUrl($url, $options), $body, $raw);
}
Performs PUT HTTP request
public mixed put ( $url, $options = [], $body = null, $raw = false ) | ||
$url | string|array |
URL |
$options | array |
URL options |
$body | string |
Request body |
$raw | boolean |
If response body contains JSON and should be decoded |
return | mixed |
Response |
---|---|---|
throws | yii\elasticsearch\Exception | |
throws | \yii\base\InvalidConfigException |
public function put($url, $options = [], $body = null, $raw = false)
{
$this->open();
return $this->httpRequest('PUT', $this->createUrl($url, $options), $body, $raw);
}
Select active node randomly
protected void selectActiveNode ( ) |
protected function selectActiveNode()
{
$keys = array_keys($this->nodes);
$this->activeNode = $keys[random_int(0, count($keys) - 1)];
}