rest.asciidoc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. [role="xpack"]
  2. [[sql-rest]]
  3. == SQL REST API
  4. * <<sql-rest-overview>>
  5. * <<sql-rest-format>>
  6. * <<sql-pagination>>
  7. * <<sql-rest-filtering>>
  8. * <<sql-rest-columnar>>
  9. * <<sql-rest-params>>
  10. * <<sql-runtime-fields>>
  11. * <<sql-async>>
  12. [[sql-rest-overview]]
  13. === Overview
  14. The <<sql-search-api,SQL search API>> accepts SQL in a JSON document, executes
  15. it, and returns the results. For example:
  16. [source,console]
  17. --------------------------------------------------
  18. POST /_sql?format=txt
  19. {
  20. "query": "SELECT * FROM library ORDER BY page_count DESC LIMIT 5"
  21. }
  22. --------------------------------------------------
  23. // TEST[setup:library]
  24. Which returns:
  25. [source,text]
  26. --------------------------------------------------
  27. author | name | page_count | release_date
  28. -----------------+--------------------+---------------+------------------------
  29. Peter F. Hamilton|Pandora's Star |768 |2004-03-02T00:00:00.000Z
  30. Vernor Vinge |A Fire Upon the Deep|613 |1992-06-01T00:00:00.000Z
  31. Frank Herbert |Dune |604 |1965-06-01T00:00:00.000Z
  32. Alastair Reynolds|Revelation Space |585 |2000-03-15T00:00:00.000Z
  33. James S.A. Corey |Leviathan Wakes |561 |2011-06-02T00:00:00.000Z
  34. --------------------------------------------------
  35. // TESTRESPONSE[s/\|/\\|/ s/\+/\\+/]
  36. // TESTRESPONSE[non_json]
  37. [[sql-kibana-console]]
  38. [TIP]
  39. .Using Kibana Console
  40. ====
  41. If you are using {kibana-ref}/console-kibana.html[Kibana Console]
  42. (which is highly recommended), take advantage of the
  43. triple quotes `"""` when creating the query. This not only automatically escapes double
  44. quotes (`"`) inside the query string but also support multi-line as shown below:
  45. image:images/sql/rest/console-triple-quotes.png[]
  46. ====
  47. [[sql-rest-format]]
  48. === Response Data Formats
  49. While the textual format is nice for humans, computers prefer something
  50. more structured.
  51. {es-sql} can return the data in the following formats which can be set
  52. either through the `format` property in the URL or by setting the `Accept` HTTP header:
  53. NOTE: The URL parameter takes precedence over the `Accept` HTTP header.
  54. If neither is specified then the response is returned in the same format as the request.
  55. [cols="^m,^4m,^8"]
  56. |===
  57. s|format
  58. s|`Accept` HTTP header
  59. s|Description
  60. 3+h| Human Readable
  61. |csv
  62. |text/csv
  63. |{wikipedia}/Comma-separated_values[Comma-separated values]
  64. |json
  65. |application/json
  66. |https://www.json.org/[JSON] (JavaScript Object Notation) human-readable format
  67. |tsv
  68. |text/tab-separated-values
  69. |{wikipedia}/Tab-separated_values[Tab-separated values]
  70. |txt
  71. |text/plain
  72. |CLI-like representation
  73. |yaml
  74. |application/yaml
  75. |{wikipedia}/YAML[YAML] (YAML Ain't Markup Language) human-readable format
  76. 3+h| Binary Formats
  77. |cbor
  78. |application/cbor
  79. |https://cbor.io/[Concise Binary Object Representation]
  80. |smile
  81. |application/smile
  82. |{wikipedia}/Smile_(data_interchange_format)[Smile] binary data format similar to CBOR
  83. |===
  84. The `CSV` format accepts a formatting URL query attribute, `delimiter`, which indicates which character should be used to separate the CSV
  85. values. It defaults to comma (`,`) and cannot take any of the following values: double quote (`"`), carriage-return (`\r`) and new-line (`\n`).
  86. The tab (`\t`) can also not be used, the `tsv` format needs to be used instead.
  87. Here are some examples for the human readable formats:
  88. ==== CSV
  89. [source,console]
  90. --------------------------------------------------
  91. POST /_sql?format=csv
  92. {
  93. "query": "SELECT * FROM library ORDER BY page_count DESC",
  94. "fetch_size": 5
  95. }
  96. --------------------------------------------------
  97. // TEST[setup:library]
  98. which returns:
  99. [source,text]
  100. --------------------------------------------------
  101. author,name,page_count,release_date
  102. Peter F. Hamilton,Pandora's Star,768,2004-03-02T00:00:00.000Z
  103. Vernor Vinge,A Fire Upon the Deep,613,1992-06-01T00:00:00.000Z
  104. Frank Herbert,Dune,604,1965-06-01T00:00:00.000Z
  105. Alastair Reynolds,Revelation Space,585,2000-03-15T00:00:00.000Z
  106. James S.A. Corey,Leviathan Wakes,561,2011-06-02T00:00:00.000Z
  107. --------------------------------------------------
  108. // TESTRESPONSE[non_json]
  109. or:
  110. [source,console]
  111. --------------------------------------------------
  112. POST /_sql?format=csv&delimiter=%3b
  113. {
  114. "query": "SELECT * FROM library ORDER BY page_count DESC",
  115. "fetch_size": 5
  116. }
  117. --------------------------------------------------
  118. // TEST[setup:library]
  119. which returns:
  120. [source,text]
  121. --------------------------------------------------
  122. author;name;page_count;release_date
  123. Peter F. Hamilton;Pandora's Star;768;2004-03-02T00:00:00.000Z
  124. Vernor Vinge;A Fire Upon the Deep;613;1992-06-01T00:00:00.000Z
  125. Frank Herbert;Dune;604;1965-06-01T00:00:00.000Z
  126. Alastair Reynolds;Revelation Space;585;2000-03-15T00:00:00.000Z
  127. James S.A. Corey;Leviathan Wakes;561;2011-06-02T00:00:00.000Z
  128. --------------------------------------------------
  129. // TESTRESPONSE[non_json]
  130. ==== JSON
  131. [source,console]
  132. --------------------------------------------------
  133. POST /_sql?format=json
  134. {
  135. "query": "SELECT * FROM library ORDER BY page_count DESC",
  136. "fetch_size": 5
  137. }
  138. --------------------------------------------------
  139. // TEST[setup:library]
  140. Which returns:
  141. [source,console-result]
  142. --------------------------------------------------
  143. {
  144. "columns": [
  145. {"name": "author", "type": "text"},
  146. {"name": "name", "type": "text"},
  147. {"name": "page_count", "type": "short"},
  148. {"name": "release_date", "type": "datetime"}
  149. ],
  150. "rows": [
  151. ["Peter F. Hamilton", "Pandora's Star", 768, "2004-03-02T00:00:00.000Z"],
  152. ["Vernor Vinge", "A Fire Upon the Deep", 613, "1992-06-01T00:00:00.000Z"],
  153. ["Frank Herbert", "Dune", 604, "1965-06-01T00:00:00.000Z"],
  154. ["Alastair Reynolds", "Revelation Space", 585, "2000-03-15T00:00:00.000Z"],
  155. ["James S.A. Corey", "Leviathan Wakes", 561, "2011-06-02T00:00:00.000Z"]
  156. ],
  157. "cursor": "sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWWWdrRlVfSS1TbDYtcW9lc1FJNmlYdw==:BAFmBmF1dGhvcgFmBG5hbWUBZgpwYWdlX2NvdW50AWYMcmVsZWFzZV9kYXRl+v///w8="
  158. }
  159. --------------------------------------------------
  160. // TESTRESPONSE[s/sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWWWdrRlVfSS1TbDYtcW9lc1FJNmlYdw==:BAFmBmF1dGhvcgFmBG5hbWUBZgpwYWdlX2NvdW50AWYMcmVsZWFzZV9kYXRl\+v\/\/\/w8=/$body.cursor/]
  161. ==== TSV
  162. [source,console]
  163. --------------------------------------------------
  164. POST /_sql?format=tsv
  165. {
  166. "query": "SELECT * FROM library ORDER BY page_count DESC",
  167. "fetch_size": 5
  168. }
  169. --------------------------------------------------
  170. // TEST[setup:library]
  171. Which returns:
  172. [source,text]
  173. --------------------------------------------------
  174. author name page_count release_date
  175. Peter F. Hamilton Pandora's Star 768 2004-03-02T00:00:00.000Z
  176. Vernor Vinge A Fire Upon the Deep 613 1992-06-01T00:00:00.000Z
  177. Frank Herbert Dune 604 1965-06-01T00:00:00.000Z
  178. Alastair Reynolds Revelation Space 585 2000-03-15T00:00:00.000Z
  179. James S.A. Corey Leviathan Wakes 561 2011-06-02T00:00:00.000Z
  180. --------------------------------------------------
  181. // TESTRESPONSE[s/\t/ /]
  182. // TESTRESPONSE[non_json]
  183. ==== TXT
  184. [source,console]
  185. --------------------------------------------------
  186. POST /_sql?format=txt
  187. {
  188. "query": "SELECT * FROM library ORDER BY page_count DESC",
  189. "fetch_size": 5
  190. }
  191. --------------------------------------------------
  192. // TEST[setup:library]
  193. Which returns:
  194. [source,text]
  195. --------------------------------------------------
  196. author | name | page_count | release_date
  197. -----------------+--------------------+---------------+------------------------
  198. Peter F. Hamilton|Pandora's Star |768 |2004-03-02T00:00:00.000Z
  199. Vernor Vinge |A Fire Upon the Deep|613 |1992-06-01T00:00:00.000Z
  200. Frank Herbert |Dune |604 |1965-06-01T00:00:00.000Z
  201. Alastair Reynolds|Revelation Space |585 |2000-03-15T00:00:00.000Z
  202. James S.A. Corey |Leviathan Wakes |561 |2011-06-02T00:00:00.000Z
  203. --------------------------------------------------
  204. // TESTRESPONSE[s/\|/\\|/ s/\+/\\+/]
  205. // TESTRESPONSE[non_json]
  206. ==== YAML
  207. [source,console]
  208. --------------------------------------------------
  209. POST /_sql?format=yaml
  210. {
  211. "query": "SELECT * FROM library ORDER BY page_count DESC",
  212. "fetch_size": 5
  213. }
  214. --------------------------------------------------
  215. // TEST[setup:library]
  216. Which returns:
  217. [source,yaml]
  218. --------------------------------------------------
  219. columns:
  220. - name: "author"
  221. type: "text"
  222. - name: "name"
  223. type: "text"
  224. - name: "page_count"
  225. type: "short"
  226. - name: "release_date"
  227. type: "datetime"
  228. rows:
  229. - - "Peter F. Hamilton"
  230. - "Pandora's Star"
  231. - 768
  232. - "2004-03-02T00:00:00.000Z"
  233. - - "Vernor Vinge"
  234. - "A Fire Upon the Deep"
  235. - 613
  236. - "1992-06-01T00:00:00.000Z"
  237. - - "Frank Herbert"
  238. - "Dune"
  239. - 604
  240. - "1965-06-01T00:00:00.000Z"
  241. - - "Alastair Reynolds"
  242. - "Revelation Space"
  243. - 585
  244. - "2000-03-15T00:00:00.000Z"
  245. - - "James S.A. Corey"
  246. - "Leviathan Wakes"
  247. - 561
  248. - "2011-06-02T00:00:00.000Z"
  249. cursor: "sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWWWdrRlVfSS1TbDYtcW9lc1FJNmlYdw==:BAFmBmF1dGhvcgFmBG5hbWUBZgpwYWdlX2NvdW50AWYMcmVsZWFzZV9kYXRl+v///w8="
  250. --------------------------------------------------
  251. // TESTRESPONSE[s/sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWWWdrRlVfSS1TbDYtcW9lc1FJNmlYdw==:BAFmBmF1dGhvcgFmBG5hbWUBZgpwYWdlX2NvdW50AWYMcmVsZWFzZV9kYXRl\+v\/\/\/w8=/$body.cursor/]
  252. [[sql-pagination]]
  253. === Paginating through a large response
  254. Using the example from the <<sql-rest-format,previous section>>, one can
  255. continue to the next page by sending back the cursor field. In the case of CSV, TSV and TXT
  256. formats, the cursor is returned in the `Cursor` HTTP header.
  257. [source,console]
  258. --------------------------------------------------
  259. POST /_sql?format=json
  260. {
  261. "cursor": "sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWYUpOYklQMHhRUEtld3RsNnFtYU1hQQ==:BAFmBGRhdGUBZgVsaWtlcwFzB21lc3NhZ2UBZgR1c2Vy9f///w8="
  262. }
  263. --------------------------------------------------
  264. // TEST[continued]
  265. // TEST[s/sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWYUpOYklQMHhRUEtld3RsNnFtYU1hQQ==:BAFmBGRhdGUBZgVsaWtlcwFzB21lc3NhZ2UBZgR1c2Vy9f\/\/\/w8=/$body.cursor/]
  266. Which looks like:
  267. [source,console-result]
  268. --------------------------------------------------
  269. {
  270. "rows" : [
  271. ["Dan Simmons", "Hyperion", 482, "1989-05-26T00:00:00.000Z"],
  272. ["Iain M. Banks", "Consider Phlebas", 471, "1987-04-23T00:00:00.000Z"],
  273. ["Neal Stephenson", "Snow Crash", 470, "1992-06-01T00:00:00.000Z"],
  274. ["Frank Herbert", "God Emperor of Dune", 454, "1981-05-28T00:00:00.000Z"],
  275. ["Frank Herbert", "Children of Dune", 408, "1976-04-21T00:00:00.000Z"]
  276. ],
  277. "cursor" : "sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWODRMaXBUaVlRN21iTlRyWHZWYUdrdw==:BAFmBmF1dGhvcgFmBG5hbWUBZgpwYWdlX2NvdW50AWYMcmVsZWFzZV9kYXRl9f///w8="
  278. }
  279. --------------------------------------------------
  280. // TESTRESPONSE[s/sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWODRMaXBUaVlRN21iTlRyWHZWYUdrdw==:BAFmBmF1dGhvcgFmBG5hbWUBZgpwYWdlX2NvdW50AWYMcmVsZWFzZV9kYXRl9f\/\/\/w8=/$body.cursor/]
  281. Note that the `columns` object is only part of the first page.
  282. You've reached the last page when there is no `cursor` returned
  283. in the results. Like Elasticsearch's <<scroll-search-results,scroll>>,
  284. SQL may keep state in Elasticsearch to support the cursor. Unlike
  285. scroll, receiving the last page is enough to guarantee that the
  286. Elasticsearch state is cleared.
  287. To clear the state earlier, use the <<clear-sql-cursor-api,clear cursor API>>:
  288. [source,console]
  289. --------------------------------------------------
  290. POST /_sql/close
  291. {
  292. "cursor": "sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWYUpOYklQMHhRUEtld3RsNnFtYU1hQQ==:BAFmBGRhdGUBZgVsaWtlcwFzB21lc3NhZ2UBZgR1c2Vy9f///w8="
  293. }
  294. --------------------------------------------------
  295. // TEST[continued]
  296. // TEST[s/sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWYUpOYklQMHhRUEtld3RsNnFtYU1hQQ==:BAFmBGRhdGUBZgVsaWtlcwFzB21lc3NhZ2UBZgR1c2Vy9f\/\/\/w8=/$body.cursor/]
  297. Which will like return the
  298. [source,console-result]
  299. --------------------------------------------------
  300. {
  301. "succeeded" : true
  302. }
  303. --------------------------------------------------
  304. [[sql-rest-filtering]]
  305. === Filtering using {es} Query DSL
  306. One can filter the results that SQL will run on using a standard
  307. {es} Query DSL by specifying the query in the filter
  308. parameter.
  309. [source,console]
  310. --------------------------------------------------
  311. POST /_sql?format=txt
  312. {
  313. "query": "SELECT * FROM library ORDER BY page_count DESC",
  314. "filter": {
  315. "range": {
  316. "page_count": {
  317. "gte" : 100,
  318. "lte" : 200
  319. }
  320. }
  321. },
  322. "fetch_size": 5
  323. }
  324. --------------------------------------------------
  325. // TEST[setup:library]
  326. Which returns:
  327. [source,text]
  328. --------------------------------------------------
  329. author | name | page_count | release_date
  330. ---------------+------------------------------------+---------------+------------------------
  331. Douglas Adams |The Hitchhiker's Guide to the Galaxy|180 |1979-10-12T00:00:00.000Z
  332. --------------------------------------------------
  333. // TESTRESPONSE[s/\|/\\|/ s/\+/\\+/]
  334. // TESTRESPONSE[non_json]
  335. [TIP]
  336. =================
  337. A useful and less obvious usage for standard Query DSL filtering is to search documents by a specific <<search-routing, routing key>>.
  338. Because {es-sql} does not support a `routing` parameter, one can specify a <<mapping-routing-field, `terms` filter for the `_routing` field>> instead:
  339. [source,console]
  340. --------------------------------------------------
  341. POST /_sql?format=txt
  342. {
  343. "query": "SELECT * FROM library",
  344. "filter": {
  345. "terms": {
  346. "_routing": ["abc"]
  347. }
  348. }
  349. }
  350. --------------------------------------------------
  351. // TEST[setup:library]
  352. =================
  353. [[sql-rest-columnar]]
  354. === Columnar results
  355. The most well known way of displaying the results of an SQL query result in general is the one where each
  356. individual record/document represents one line/row. For certain formats, {es-sql} can return the results
  357. in a columnar fashion: one row represents all the values of a certain column from the current page of results.
  358. The following formats can be returned in columnar orientation: `json`, `yaml`, `cbor` and `smile`.
  359. [source,console]
  360. --------------------------------------------------
  361. POST /_sql?format=json
  362. {
  363. "query": "SELECT * FROM library ORDER BY page_count DESC",
  364. "fetch_size": 5,
  365. "columnar": true
  366. }
  367. --------------------------------------------------
  368. // TEST[setup:library]
  369. Which returns:
  370. [source,console-result]
  371. --------------------------------------------------
  372. {
  373. "columns": [
  374. {"name": "author", "type": "text"},
  375. {"name": "name", "type": "text"},
  376. {"name": "page_count", "type": "short"},
  377. {"name": "release_date", "type": "datetime"}
  378. ],
  379. "values": [
  380. ["Peter F. Hamilton", "Vernor Vinge", "Frank Herbert", "Alastair Reynolds", "James S.A. Corey"],
  381. ["Pandora's Star", "A Fire Upon the Deep", "Dune", "Revelation Space", "Leviathan Wakes"],
  382. [768, 613, 604, 585, 561],
  383. ["2004-03-02T00:00:00.000Z", "1992-06-01T00:00:00.000Z", "1965-06-01T00:00:00.000Z", "2000-03-15T00:00:00.000Z", "2011-06-02T00:00:00.000Z"]
  384. ],
  385. "cursor": "sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWWWdrRlVfSS1TbDYtcW9lc1FJNmlYdw==:BAFmBmF1dGhvcgFmBG5hbWUBZgpwYWdlX2NvdW50AWYMcmVsZWFzZV9kYXRl+v///w8="
  386. }
  387. --------------------------------------------------
  388. // TESTRESPONSE[s/sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWWWdrRlVfSS1TbDYtcW9lc1FJNmlYdw==:BAFmBmF1dGhvcgFmBG5hbWUBZgpwYWdlX2NvdW50AWYMcmVsZWFzZV9kYXRl\+v\/\/\/w8=/$body.cursor/]
  389. Any subsequent calls using a `cursor` still have to contain the `columnar` parameter to preserve the orientation,
  390. meaning the initial query will not _remember_ the columnar option.
  391. [source,console]
  392. --------------------------------------------------
  393. POST /_sql?format=json
  394. {
  395. "cursor": "sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWWWdrRlVfSS1TbDYtcW9lc1FJNmlYdw==:BAFmBmF1dGhvcgFmBG5hbWUBZgpwYWdlX2NvdW50AWYMcmVsZWFzZV9kYXRl+v///w8=",
  396. "columnar": true
  397. }
  398. --------------------------------------------------
  399. // TEST[continued]
  400. // TEST[s/sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWWWdrRlVfSS1TbDYtcW9lc1FJNmlYdw==:BAFmBmF1dGhvcgFmBG5hbWUBZgpwYWdlX2NvdW50AWYMcmVsZWFzZV9kYXRl\+v\/\/\/w8=/$body.cursor/]
  401. Which looks like:
  402. [source,console-result]
  403. --------------------------------------------------
  404. {
  405. "values": [
  406. ["Dan Simmons", "Iain M. Banks", "Neal Stephenson", "Frank Herbert", "Frank Herbert"],
  407. ["Hyperion", "Consider Phlebas", "Snow Crash", "God Emperor of Dune", "Children of Dune"],
  408. [482, 471, 470, 454, 408],
  409. ["1989-05-26T00:00:00.000Z", "1987-04-23T00:00:00.000Z", "1992-06-01T00:00:00.000Z", "1981-05-28T00:00:00.000Z", "1976-04-21T00:00:00.000Z"]
  410. ],
  411. "cursor": "46ToAwFzQERYRjFaWEo1UVc1a1JtVjBZMmdCQUFBQUFBQUFBQUVXWjBaNlFXbzNOV0pVY21Wa1NUZDJhV2t3V2xwblp3PT3/////DwQBZgZhdXRob3IBBHRleHQAAAFmBG5hbWUBBHRleHQAAAFmCnBhZ2VfY291bnQBBGxvbmcBAAFmDHJlbGVhc2VfZGF0ZQEIZGF0ZXRpbWUBAAEP"
  412. }
  413. --------------------------------------------------
  414. // TESTRESPONSE[s/46ToAwFzQERYRjFaWEo1UVc1a1JtVjBZMmdCQUFBQUFBQUFBQUVXWjBaNlFXbzNOV0pVY21Wa1NUZDJhV2t3V2xwblp3PT3\/\/\/\/\/DwQBZgZhdXRob3IBBHRleHQAAAFmBG5hbWUBBHRleHQAAAFmCnBhZ2VfY291bnQBBGxvbmcBAAFmDHJlbGVhc2VfZGF0ZQEIZGF0ZXRpbWUBAAEP/$body.cursor/]
  415. [[sql-rest-params]]
  416. === Passing parameters to a query
  417. Using values in a query condition, for example, or in a `HAVING` statement can be done "inline",
  418. by integrating the value in the query string itself:
  419. [source,console]
  420. --------------------------------------------------
  421. POST /_sql?format=txt
  422. {
  423. "query": "SELECT YEAR(release_date) AS year FROM library WHERE page_count > 300 AND author = 'Frank Herbert' GROUP BY year HAVING COUNT(*) > 0"
  424. }
  425. --------------------------------------------------
  426. // TEST[setup:library]
  427. or it can be done by extracting the values in a separate list of parameters and using question mark placeholders (`?`) in the query string:
  428. [source,console]
  429. --------------------------------------------------
  430. POST /_sql?format=txt
  431. {
  432. "query": "SELECT YEAR(release_date) AS year FROM library WHERE page_count > ? AND author = ? GROUP BY year HAVING COUNT(*) > ?",
  433. "params": [300, "Frank Herbert", 0]
  434. }
  435. --------------------------------------------------
  436. // TEST[setup:library]
  437. [IMPORTANT]
  438. The recommended way of passing values to a query is with question mark placeholders, to avoid any attempts of hacking or SQL injection.
  439. [[sql-runtime-fields]]
  440. === Use runtime fields
  441. Use the `runtime_mappings` parameter to extract and create <<runtime,runtime
  442. fields>>, or columns, from existing ones during a search.
  443. The following search creates a `release_day_of_week` runtime field from
  444. `release_date` and returns it in the response.
  445. [source,console]
  446. ----
  447. POST _sql?format=txt
  448. {
  449. "runtime_mappings": {
  450. "release_day_of_week": {
  451. "type": "keyword",
  452. "script": """
  453. emit(doc['release_date'].value.dayOfWeekEnum.toString())
  454. """
  455. }
  456. },
  457. "query": """
  458. SELECT * FROM library WHERE page_count > 300 AND author = 'Frank Herbert'
  459. """
  460. }
  461. ----
  462. // TEST[setup:library]
  463. The API returns:
  464. [source,txt]
  465. ----
  466. author | name | page_count | release_date |release_day_of_week
  467. ---------------+---------------+---------------+------------------------+-------------------
  468. Frank Herbert |Dune |604 |1965-06-01T00:00:00.000Z|TUESDAY
  469. ----
  470. // TESTRESPONSE[non_json]
  471. [[sql-async]]
  472. === Run an async SQL search
  473. By default, SQL searches are synchronous. They wait for complete results before
  474. returning a response. However, results can take longer for searches across large
  475. data sets or <<data-tiers,frozen data>>.
  476. To avoid long waits, run an async SQL search. Set `wait_for_completion_timeout`
  477. to a duration you’d like to wait for synchronous results.
  478. [source,console]
  479. ----
  480. POST _sql?format=json
  481. {
  482. "wait_for_completion_timeout": "2s",
  483. "query": "SELECT * FROM library ORDER BY page_count DESC",
  484. "fetch_size": 5
  485. }
  486. ----
  487. // TEST[skip:waiting on https://github.com/elastic/elasticsearch/issues/75069]
  488. // TEST[setup:library]
  489. // TEST[s/"wait_for_completion_timeout": "2s"/"wait_for_completion_timeout": "0"/]
  490. If the search doesn’t finish within this period, the search becomes async. The
  491. API returns:
  492. * An `id` for the search.
  493. * An `is_partial` value of `true`, indicating the search results are incomplete.
  494. * An `is_running` value of `true`, indicating the search is still running in the
  495. background.
  496. For CSV, TSV, and TXT responses, the API returns these values in the respective
  497. `Async-ID`, `Async-partial`, and `Async-running` HTTP headers instead.
  498. [source,console-result]
  499. ----
  500. {
  501. "id": "FnR0TDhyWUVmUmVtWXRWZER4MXZiNFEad2F5UDk2ZVdTVHV1S0xDUy00SklUdzozMTU=",
  502. "is_partial": true,
  503. "is_running": true,
  504. "rows": [ ]
  505. }
  506. ----
  507. // TESTRESPONSE[skip:waiting on https://github.com/elastic/elasticsearch/issues/75069]
  508. // TESTRESPONSE[s/FnR0TDhyWUVmUmVtWXRWZER4MXZiNFEad2F5UDk2ZVdTVHV1S0xDUy00SklUdzozMTU=/$body.id/]
  509. // TESTRESPONSE[s/"is_partial": true/"is_partial": $body.is_partial/]
  510. // TESTRESPONSE[s/"is_running": true/"is_running": $body.is_running/]
  511. To check the progress of an async search, use the search ID with the
  512. <<get-async-sql-search-status-api,get async SQL search status API>>.
  513. [source,console]
  514. ----
  515. GET _sql/async/status/FnR0TDhyWUVmUmVtWXRWZER4MXZiNFEad2F5UDk2ZVdTVHV1S0xDUy00SklUdzozMTU=
  516. ----
  517. // TEST[skip: no access to search ID]
  518. If `is_running` and `is_partial` are `false`, the async search has finished with
  519. complete results.
  520. [source,console-result]
  521. ----
  522. {
  523. "id": "FnR0TDhyWUVmUmVtWXRWZER4MXZiNFEad2F5UDk2ZVdTVHV1S0xDUy00SklUdzozMTU=",
  524. "is_running": false,
  525. "is_partial": false,
  526. "expiration_time_in_millis": 1611690295000,
  527. "completion_status": 200
  528. }
  529. ----
  530. // TESTRESPONSE[skip:waiting on https://github.com/elastic/elasticsearch/issues/75069]
  531. // TESTRESPONSE[s/FnR0TDhyWUVmUmVtWXRWZER4MXZiNFEad2F5UDk2ZVdTVHV1S0xDUy00SklUdzozMTU=/$body.id/]
  532. // TESTRESPONSE[s/"expiration_time_in_millis": 1611690295000/"expiration_time_in_millis": $body.expiration_time_in_millis/]
  533. To get the results, use the search ID with the <<get-async-sql-search-api,get
  534. async SQL search API>>. If the search is still running, specify how long you’d
  535. like to wait using `wait_for_completion_timeout`. You can also specify the
  536. response `format`.
  537. [source,console]
  538. ----
  539. GET _sql/async/FnR0TDhyWUVmUmVtWXRWZER4MXZiNFEad2F5UDk2ZVdTVHV1S0xDUy00SklUdzozMTU=?wait_for_completion_timeout=2s&format=json
  540. ----
  541. // TEST[skip: no access to search ID]
  542. [discrete]
  543. [[sql-async-retention]]
  544. ==== Change the search retention period
  545. By default, {es} stores async SQL searches for five days. After this period,
  546. {es} deletes the search and its results, even if the search is still running. To
  547. change this retention period, use the `keep_alive` parameter.
  548. [source,console]
  549. ----
  550. POST _sql?format=json
  551. {
  552. "keep_alive": "2d",
  553. "wait_for_completion_timeout": "2s",
  554. "query": "SELECT * FROM library ORDER BY page_count DESC",
  555. "fetch_size": 5
  556. }
  557. ----
  558. // TEST[skip:waiting on https://github.com/elastic/elasticsearch/issues/75069]
  559. // TEST[setup:library]
  560. You can use the get async SQL search API's `keep_alive` parameter to later
  561. change the retention period. The new period starts after the request runs.
  562. [source,console]
  563. ----
  564. GET _sql/async/FmdMX2pIang3UWhLRU5QS0lqdlppYncaMUpYQ05oSkpTc3kwZ21EdC1tbFJXQToxOTI=?keep_alive=5d&wait_for_completion_timeout=2s&format=json
  565. ----
  566. // TEST[skip: no access to search ID]
  567. Use the <<delete-async-sql-search-api,delete async SQL search API>> to delete an
  568. async search before the `keep_alive` period ends. If the search is still
  569. running, {es} cancels it.
  570. [source,console]
  571. ----
  572. DELETE _sql/async/delete/FmdMX2pIang3UWhLRU5QS0lqdlppYncaMUpYQ05oSkpTc3kwZ21EdC1tbFJXQToxOTI=
  573. ----
  574. // TEST[skip: no access to search ID]
  575. [discrete]
  576. [[sql-store-searches]]
  577. ==== Store synchronous SQL searches
  578. By default, {es} only stores async SQL searches. To save a synchronous search,
  579. specify `wait_for_completion_timeout` and set `keep_on_completion` to `true`.
  580. [source,console]
  581. ----
  582. POST _sql?format=json
  583. {
  584. "keep_on_completion": true,
  585. "wait_for_completion_timeout": "2s",
  586. "query": "SELECT * FROM library ORDER BY page_count DESC",
  587. "fetch_size": 5
  588. }
  589. ----
  590. // TEST[skip:waiting on https://github.com/elastic/elasticsearch/issues/75069]
  591. // TEST[setup:library]
  592. If `is_partial` and `is_running` are `false`, the search was synchronous and
  593. returned complete results.
  594. [source,console-result]
  595. ----
  596. {
  597. "id": "Fnc5UllQdUVWU0NxRFNMbWxNYXplaFEaMUpYQ05oSkpTc3kwZ21EdC1tbFJXQTo0NzA=",
  598. "is_partial": false,
  599. "is_running": false,
  600. "rows": ...,
  601. "columns": ...,
  602. "cursor": ...
  603. }
  604. ----
  605. // TESTRESPONSE[skip:waiting on https://github.com/elastic/elasticsearch/issues/75069]
  606. // TESTRESPONSE[s/Fnc5UllQdUVWU0NxRFNMbWxNYXplaFEaMUpYQ05oSkpTc3kwZ21EdC1tbFJXQTo0NzA=/$body.id/]
  607. // TESTRESPONSE[s/"rows": \.\.\./"rows": $body.rows/]
  608. // TESTRESPONSE[s/"columns": \.\.\./"columns": $body.columns/]
  609. // TESTRESPONSE[s/"cursor": \.\.\./"cursor": $body.cursor/]
  610. You can get the same results later using the search ID with the
  611. <<get-async-sql-search-api,get async SQL search API>>.
  612. Saved synchronous searches are still subject to the `keep_alive` retention
  613. period. When this period ends, {es} deletes the search results. You can also
  614. delete saved searches using the <<delete-async-sql-search-api,delete async SQL
  615. search API>>.