2018-06-22 18:40:25 -04:00
[role="xpack"]
[testenv="basic"]
2017-12-13 10:19:31 -05:00
[[sql-rest]]
== SQL REST API
The SQL REST API accepts SQL in a JSON document, executes it,
2019-02-15 14:15:40 -05:00
and returns the results.
For example:
2017-12-13 10:19:31 -05:00
[source,js]
--------------------------------------------------
2018-11-27 22:16:21 -05:00
POST /_sql?format=txt
2017-12-13 10:19:31 -05:00
{
"query": "SELECT * FROM library ORDER BY page_count DESC LIMIT 5"
}
--------------------------------------------------
// CONSOLE
// TEST[setup:library]
Which returns:
[source,text]
--------------------------------------------------
author | name | page_count | release_date
2018-01-08 14:52:27 -05:00
-----------------+--------------------+---------------+------------------------
Peter F. Hamilton|Pandora's Star |768 |2004-03-02T00:00:00.000Z
Vernor Vinge |A Fire Upon the Deep|613 |1992-06-01T00:00:00.000Z
Frank Herbert |Dune |604 |1965-06-01T00:00:00.000Z
Alastair Reynolds|Revelation Space |585 |2000-03-15T00:00:00.000Z
James S.A. Corey |Leviathan Wakes |561 |2011-06-02T00:00:00.000Z
2017-12-13 10:19:31 -05:00
--------------------------------------------------
2017-12-18 20:57:50 -05:00
// TESTRESPONSE[s/\|/\\|/ s/\+/\\+/]
2017-12-13 10:19:31 -05:00
// TESTRESPONSE[_cat]
2019-02-15 14:15:40 -05:00
[[sql-kibana-console]]
.Using Kibana Console
If you are using {kibana-ref}/console-kibana.html[Kibana Console].
(which is highly recommended), take advantage of the
triple quotes `"""` when creating the query. This not only automatically escapes double
quotes (`"`) inside the query string but also support multi-line as shown below:
image:images/sql/rest/console-triple-quotes.png[]
[[sql-rest-format]]
[float]
=== Response Data Formats
While the textual format is nice for humans, computers prefer something
more structured.
{es-sql} can return the data in the following formats which can be set
either through the `format` property in the URL or by setting the `Accept` HTTP header:
NOTE: The URL parameter takes precedence over the `Accept` HTTP header.
If neither is specified then the response is returned in the same format as the request.
[cols="^m,^4m,^8"]
|===
s|format
s|`Accept` HTTP header
s|Description
3+h| Human Readable
|csv
|text/csv
|https://en.wikipedia.org/wiki/Comma-separated_values[Comma-separated values]
|json
|application/json
|https://www.json.org/[JSON] (JavaScript Object Notation) human-readable format
|tsv
|text/tab-separated-values
|https://en.wikipedia.org/wiki/Tab-separated_values[Tab-separated values]
|txt
|text/plain
|CLI-like representation
|yaml
|application/yaml
|https://en.wikipedia.org/wiki/YAML[YAML] (YAML Ain't Markup Language) human-readable format
3+h| Binary Formats
|cbor
|application/cbor
|http://cbor.io/[Concise Binary Object Representation]
|smile
|application/smile
|https://en.wikipedia.org/wiki/Smile_(data_interchange_format)[Smile] binary data format similar to CBOR
|===
2017-12-13 10:19:31 -05:00
[source,js]
--------------------------------------------------
2018-11-27 22:16:21 -05:00
POST /_sql?format=json
2017-12-13 10:19:31 -05:00
{
"query": "SELECT * FROM library ORDER BY page_count DESC",
"fetch_size": 5
}
--------------------------------------------------
// CONSOLE
// TEST[setup:library]
Which returns:
[source,js]
--------------------------------------------------
{
"columns": [
2018-01-10 09:41:36 -05:00
{"name": "author", "type": "text"},
{"name": "name", "type": "text"},
{"name": "page_count", "type": "short"},
2019-01-17 03:17:58 -05:00
{"name": "release_date", "type": "datetime"}
2017-12-13 10:19:31 -05:00
],
"rows": [
2018-01-08 14:52:27 -05:00
["Peter F. Hamilton", "Pandora's Star", 768, "2004-03-02T00:00:00.000Z"],
["Vernor Vinge", "A Fire Upon the Deep", 613, "1992-06-01T00:00:00.000Z"],
["Frank Herbert", "Dune", 604, "1965-06-01T00:00:00.000Z"],
["Alastair Reynolds", "Revelation Space", 585, "2000-03-15T00:00:00.000Z"],
["James S.A. Corey", "Leviathan Wakes", 561, "2011-06-02T00:00:00.000Z"]
2017-12-13 10:19:31 -05:00
],
"cursor": "sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWWWdrRlVfSS1TbDYtcW9lc1FJNmlYdw==:BAFmBmF1dGhvcgFmBG5hbWUBZgpwYWdlX2NvdW50AWYMcmVsZWFzZV9kYXRl+v///w8="
}
--------------------------------------------------
// TESTRESPONSE[s/sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWWWdrRlVfSS1TbDYtcW9lc1FJNmlYdw==:BAFmBmF1dGhvcgFmBG5hbWUBZgpwYWdlX2NvdW50AWYMcmVsZWFzZV9kYXRl\+v\/\/\/w8=/$body.cursor/]
2019-02-15 14:15:40 -05:00
[[sql-pagination]]
[float]
=== Paginating through a large response
Using the example above, onu can continue to the next page by sending back the `cursor` field. In
2017-12-13 10:19:31 -05:00
case of text format the cursor is returned as `Cursor` http header.
[source,js]
--------------------------------------------------
2018-11-27 22:16:21 -05:00
POST /_sql?format=json
2017-12-13 10:19:31 -05:00
{
"cursor": "sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWYUpOYklQMHhRUEtld3RsNnFtYU1hQQ==:BAFmBGRhdGUBZgVsaWtlcwFzB21lc3NhZ2UBZgR1c2Vy9f///w8="
}
--------------------------------------------------
// CONSOLE
// TEST[continued]
// TEST[s/sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWYUpOYklQMHhRUEtld3RsNnFtYU1hQQ==:BAFmBGRhdGUBZgVsaWtlcwFzB21lc3NhZ2UBZgR1c2Vy9f\/\/\/w8=/$body.cursor/]
Which looks like:
[source,js]
--------------------------------------------------
{
"rows" : [
2018-01-08 14:52:27 -05:00
["Dan Simmons", "Hyperion", 482, "1989-05-26T00:00:00.000Z"],
["Iain M. Banks", "Consider Phlebas", 471, "1987-04-23T00:00:00.000Z"],
["Neal Stephenson", "Snow Crash", 470, "1992-06-01T00:00:00.000Z"],
["Frank Herbert", "God Emperor of Dune", 454, "1981-05-28T00:00:00.000Z"],
["Frank Herbert", "Children of Dune", 408, "1976-04-21T00:00:00.000Z"]
2017-12-13 10:19:31 -05:00
],
"cursor" : "sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWODRMaXBUaVlRN21iTlRyWHZWYUdrdw==:BAFmBmF1dGhvcgFmBG5hbWUBZgpwYWdlX2NvdW50AWYMcmVsZWFzZV9kYXRl9f///w8="
}
--------------------------------------------------
// TESTRESPONSE[s/sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWODRMaXBUaVlRN21iTlRyWHZWYUdrdw==:BAFmBmF1dGhvcgFmBG5hbWUBZgpwYWdlX2NvdW50AWYMcmVsZWFzZV9kYXRl9f\/\/\/w8=/$body.cursor/]
2019-02-15 14:15:40 -05:00
Note that the `columns` object is only part of the first page.
2017-12-13 10:19:31 -05:00
You've reached the last page when there is no `cursor` returned
in the results. Like Elasticsearch's <<search-request-scroll,scroll>>,
SQL may keep state in Elasticsearch to support the cursor. Unlike
scroll, receiving the last page is enough to guarantee that the
Elasticsearch state is cleared.
To clear the state earlier, you can use the clear cursor command:
[source,js]
--------------------------------------------------
2018-11-27 22:16:21 -05:00
POST /_sql/close
2017-12-13 10:19:31 -05:00
{
"cursor": "sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWYUpOYklQMHhRUEtld3RsNnFtYU1hQQ==:BAFmBGRhdGUBZgVsaWtlcwFzB21lc3NhZ2UBZgR1c2Vy9f///w8="
}
--------------------------------------------------
// CONSOLE
// TEST[continued]
// TEST[s/sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWYUpOYklQMHhRUEtld3RsNnFtYU1hQQ==:BAFmBGRhdGUBZgVsaWtlcwFzB21lc3NhZ2UBZgR1c2Vy9f\/\/\/w8=/$body.cursor/]
Which will like return the
[source,js]
--------------------------------------------------
{
"succeeded" : true
}
--------------------------------------------------
// TESTRESPONSE
[[sql-rest-filtering]]
2019-02-15 14:15:40 -05:00
[float]
=== Filtering using {es} query DSL
2017-12-13 10:19:31 -05:00
You can filter the results that SQL will run on using a standard
2019-02-15 14:15:40 -05:00
{es} query DSL by specifying the query in the filter
2017-12-13 10:19:31 -05:00
parameter.
[source,js]
--------------------------------------------------
2018-11-27 22:16:21 -05:00
POST /_sql?format=txt
2017-12-13 10:19:31 -05:00
{
"query": "SELECT * FROM library ORDER BY page_count DESC",
"filter": {
"range": {
"page_count": {
"gte" : 100,
"lte" : 200
}
}
},
"fetch_size": 5
}
--------------------------------------------------
// CONSOLE
// TEST[setup:library]
Which returns:
[source,text]
--------------------------------------------------
author | name | page_count | release_date
2018-01-08 14:52:27 -05:00
---------------+------------------------------------+---------------+------------------------
Douglas Adams |The Hitchhiker's Guide to the Galaxy|180 |1979-10-12T00:00:00.000Z
2017-12-13 10:19:31 -05:00
--------------------------------------------------
2017-12-18 20:57:50 -05:00
// TESTRESPONSE[s/\|/\\|/ s/\+/\\+/]
2017-12-13 10:19:31 -05:00
// TESTRESPONSE[_cat]
[[sql-rest-fields]]
2019-02-15 14:15:40 -05:00
[float]
=== Supported REST parameters
In addition to the `query` and `fetch_size`, a request a number of user-defined fields for specifying
the request time-outs or localization information (such as timezone).
The table below lists the supported parameters:
[cols="^m,^m,^5"]
|===
s|name
s|Default value
s|Description
|query
|Mandatory
|SQL query to execute
|fetch_size
|1000
|The maximum number of rows (or entries) to return in one response
|filter
|none
|Optional {es} query DSL for additional <<sql-rest-filtering, filtering>>.
|request_timeout
|90s
|The timeout before the request fails.
|page_timeout
|45s
|The timeout before a pagination request fails.
|time_zone
|`Z` (or `UTC`)
|Time-zone in ISO 8601 used for executing the query on the server.
More information available https://docs.oracle.com/javase/8/docs/api/java/time/ZoneId.html[here].
|===
Do note that most parameters (outside the timeout ones) make sense only during the initial query - any follow-up pagination request only requires the `cursor` parameter as explained in the <<sql-pagination, pagination>> chapter.
That's because the query has already been executed and the calls are simply about returning the found results - thus the parameters are simply ignored.