Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions docs/reference/esql.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ There are two ways to use ES|QL in the PHP client:
* Use the Elasticsearch [ES|QL API](https://www.elastic.co/docs/api/doc/elasticsearch/group/endpoint-esql) directly: This is the most flexible approach, but it’s also the most complex because you must handle results in their raw form. You can choose the precise format of results, such as JSON, CSV, or text.
* Use ES|QL `mapTo($class)` helper. This mapper takes care of parsing the raw response and converting into an array of objects. If you don’t specify the class using the `$class` parameter, the mapper uses [stdClass](https://www.php.net/manual/en/class.stdclass.php).

ES|QL queries can be given directly as regular strings or heredoc strings, or for a more convenient option you can use the [ES|QL query builder](#esql-query-builder) helper, which can define ES|QL queries using PHP code.

## How to use the ES|QL API [esql-how-to]

Expand Down Expand Up @@ -206,3 +207,71 @@ $result = $client->esql()->query([
$books = $result->mapTo(Book::class); // Array of Book
```

## Using the ES|QL query builder [esql-query-builder]

::::{warning}
This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.
::::

The ES|QL query builder allows you to construct ES|QL queries using PHP syntax. Consider the following example:

```php
use Elastic\Elasticsearch\Helper\Esql\Query;

$query = Query::from("employees")
->sort("emp_no")
->keep("first_name", "last_name", "height")
->eval(height_feet: "height * 3.281", height_cm: "height * 100")
->limit(3);
```

Casting this query object to a string returns the raw ES|QL query, which you can send to the Elasticsearch ES|QL API:

```php
$result = $client->esql()->query([
'body' => ['query' => (string)$query]
]);
```

### Creating an ES|QL query

To construct an ES|QL query object you typically use `Query::from()`, although there are more [source commands](https://www.elastic.co/docs/reference/query-languages/esql/commands/source-commands) available. Here are some examples:

```php
// FROM employees
$query = Query::from("employees");

// FROM <logs-{now/d}>
$query = Query::from("<logs-{now/d}>");

// FROM employees-00001, other-employees-*
$query = Query::from("employees-00001", "other-employees-*");

// FROM cluster_one:employees-00001, cluster_two:other-employees-*
$query = Query::from("cluster_one:employees-00001", "cluster_two:other-employees-*");

// FROM employees METADATA _id
$query = Query::from("employees")->metadata("_id");
```

Note how in the last example the optional `METADATA` clause of the `FROM` command is added as a chained method.

### Adding processing commands

Once you have a query object, you can add one or more processing commands to it by chaining them. The following example shows how to create a query that uses the `WHERE` and `LIMIT` processing commands to filter the results:

```php
$query = Query::from("employees")
->where("still_hired == true")
->limit(10);
```

The ES|QL documentation includes the complete list of available [processing commands](https://www.elastic.co/docs/reference/query-languages/esql/commands/processing-commands).

### Using Code completion

You can rely on autocompletion as an aid in constructing ES|QL queries with the query builder. Note that this requires an IDE that is configured with a PHP language server.

![Autocompleting Query::](images/autocompleting-query.png)

![Autocompleting from()](images/autocompleting-from.png)
Binary file added docs/reference/images/autocompleting-from.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 33 additions & 0 deletions src/Helper/Esql/Branch.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php
/**
* Elasticsearch PHP Client
*
* @link https://github.com/elastic/elasticsearch-php
* @copyright Copyright (c) Elasticsearch B.V (https://www.elastic.co)
* @license https://opensource.org/licenses/MIT MIT License
*
* Licensed to Elasticsearch B.V under one or more agreements.
* Elasticsearch B.V licenses this file to you under the MIT License.
* See the LICENSE file in the project root for more information.
*/
declare(strict_types = 1);

namespace Elastic\Elasticsearch\Helper\Esql;

/**
* Implementation of a branch inside a `FORK` processing command.
*
* This class inherits from EsqlBase to make it possible to chain all the commands
* that belong to an ES|QL query in a single expression.
*/
class Branch extends EsqlBase {
public function __construct()
{
parent::__construct(null);
}

protected function renderInternal(): string
{
return "";
}
}
72 changes: 72 additions & 0 deletions src/Helper/Esql/ChangePointCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php
/**
* Elasticsearch PHP Client
*
* @link https://github.com/elastic/elasticsearch-php
* @copyright Copyright (c) Elasticsearch B.V (https://www.elastic.co)
* @license https://opensource.org/licenses/MIT MIT License
*
* Licensed to Elasticsearch B.V under one or more agreements.
* Elasticsearch B.V licenses this file to you under the MIT License.
* See the LICENSE file in the project root for more information.
*/
declare(strict_types = 1);

namespace Elastic\Elasticsearch\Helper\Esql;

/**
* Implementation of the `CHANGE_POINT` processing command.
*
* This class inherits from EsqlBase to make it possible to chain all the commands
* that belong to an ES|QL query in a single expression.
*/
class ChangePointCommand extends EsqlBase {
private string $value;
private string $key = "";
private string $type_name = "";
private string $pvalue_name = "";

public function __construct(EsqlBase $previous_command, string $value)
{
parent::__construct($previous_command);
$this->value = $value;
}

/**
* Continuation of the `CHANGE_POINT` command.
*
* @param string $key The column with the key to order the values by. If not
* specified, `@timestamp` is used.
*/
public function on(string $key): ChangePointCommand
{
$this->key = $key;
return $this;
}

/**
* Continuation of the `CHANGE_POINT` command.
*
* @param string $type_name The name of the output column with the change
* point type. If not specified, `type` is used.
* @param string $pvalue_name The name of the output column with the p-value
* that indicates how extreme the change point is.
* If not specified, `pvalue` is used.
*/
public function as(string $type_name, string $pvalue_name): ChangePointCommand
{
$this->type_name = $type_name;
$this->pvalue_name = $pvalue_name;
return $this;
}

protected function renderInternal(): string
{
$key = $this->key ? " ON " . $this->formatId($this->key) : "";
$names = ($this->type_name && $this->pvalue_name) ?
" AS " . $this->formatId($this->type_name) . ", " .
$this->formatId($this->pvalue_name)
: "";
return "CHANGE_POINT " . $this->value . $key . $names;
}
}
74 changes: 74 additions & 0 deletions src/Helper/Esql/CompletionCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php
/**
* Elasticsearch PHP Client
*
* @link https://github.com/elastic/elasticsearch-php
* @copyright Copyright (c) Elasticsearch B.V (https://www.elastic.co)
* @license https://opensource.org/licenses/MIT MIT License
*
* Licensed to Elasticsearch B.V under one or more agreements.
* Elasticsearch B.V licenses this file to you under the MIT License.
* See the LICENSE file in the project root for more information.
*/
declare(strict_types = 1);

namespace Elastic\Elasticsearch\Helper\Esql;

use RuntimeException;

/**
* Implementation of the `COMPLETION` processing command.
*
* This class inherits from EsqlBase to make it possible to chain all the commands
* that belong to an ES|QL query in a single expression.
*/
class CompletionCommand extends EsqlBase {
private string $prompt;
private array $named_prompt = [];
private string $inference_id = "";

public function __construct(EsqlBase $previous_command, array $prompt)
{
if (sizeof($prompt) != 1) {
throw new RuntimeException("Only one prompt is supported");
}
parent::__construct($previous_command);
if ($this->isNamedArgumentList($prompt)) {
$this->named_prompt = $prompt;
}
else {
$this->prompt = $prompt[0];
}
}

/**
* Continuation of the `COMPLETION` command.
*
* @param string $inference_id The ID of the inference endpoint to use for
* the task. The inference endpoint must be
* configured with the `completion` task type.
*/
public function with(string $inference_id): CompletionCommand
{
$this->inference_id = $inference_id;
return $this;
}

protected function renderInternal(): string
{
if (!$this->inference_id) {
throw new RuntimeException("The completion command requires an inference ID");
}
$with = ["inference_id" => $this->inference_id];
if ($this->named_prompt) {
return "COMPLETION " .
$this->formatId(array_keys($this->named_prompt)[0]) . " = " .
$this->formatId(array_values($this->named_prompt)[0]) .
" WITH " . json_encode($with);
}
else {
return "COMPLETION " . $this->formatId($this->prompt) .
" WITH " . json_encode($with);
}
}
}
52 changes: 52 additions & 0 deletions src/Helper/Esql/DissectCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php
/**
* Elasticsearch PHP Client
*
* @link https://github.com/elastic/elasticsearch-php
* @copyright Copyright (c) Elasticsearch B.V (https://www.elastic.co)
* @license https://opensource.org/licenses/MIT MIT License
*
* Licensed to Elasticsearch B.V under one or more agreements.
* Elasticsearch B.V licenses this file to you under the MIT License.
* See the LICENSE file in the project root for more information.
*/
declare(strict_types = 1);

namespace Elastic\Elasticsearch\Helper\Esql;

/**
* Implementation of the `DISSECT` processing command.
*
* This class inherits from EsqlBase to make it possible to chain all the commands
* that belong to an ES|QL query in a single expression.
*/
class DissectCommand extends EsqlBase {
private string $input;
private string $pattern;
private string $separator = "";

public function __construct(EsqlBase $previous_command, string $input, string $pattern)
{
parent::__construct($previous_command);
$this->input = $input;
$this->pattern = $pattern;
}

/**
* Continuation of the `DISSECT` command.
*
* @param string $separator A string used as the separator between appended
* values, when using the append modifier.
*/
public function append_separator(string $separator): DissectCommand
{
$this->separator = $separator;
return $this;
}

protected function renderInternal(): string
{
$sep = $this->separator ? " APPEND_SEPARATOR=" . json_encode($this->separator) : "";
return "DISSECT " . $this->formatId($this->input) . " " . json_encode($this->pattern) . $sep;
}
}
38 changes: 38 additions & 0 deletions src/Helper/Esql/DropCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php
/**
* Elasticsearch PHP Client
*
* @link https://github.com/elastic/elasticsearch-php
* @copyright Copyright (c) Elasticsearch B.V (https://www.elastic.co)
* @license https://opensource.org/licenses/MIT MIT License
*
* Licensed to Elasticsearch B.V under one or more agreements.
* Elasticsearch B.V licenses this file to you under the MIT License.
* See the LICENSE file in the project root for more information.
*/
declare(strict_types = 1);

namespace Elastic\Elasticsearch\Helper\Esql;

/**
* Implementation of the `DROP` processing command.
*
* This class inherits from EsqlBase to make it possible to chain all the commands
* that belong to an ES|QL query in a single expression.
*/
class DropCommand extends EsqlBase {
private array $columns;

public function __construct(EsqlBase $previous_command, array $columns)
{
parent::__construct($previous_command);
$this->columns = $columns;
}

protected function renderInternal(): string
{
return "DROP " . implode(
", ", array_map(array($this, "formatId"), $this->columns)
);
}
}
Loading
Loading