Asynchronous search

Searching large volumes of data can take a long time, especially if you’re searching across warm nodes or multiple remote clusters.

Asynchronous search in OpenSearch lets you send search requests that run in the background. You can monitor the progress of these searches and get back partial results as they become available. After the search finishes, you can save the results to examine at a later time.

REST API

Introduced 1.0

To perform an asynchronous search, send requests to _plugins/_asynchronous_search, with your query in the request body:

  1. POST _plugins/_asynchronous_search

You can specify the following options.

OptionsDescriptionDefault valueRequired
wait_for_completion_timeoutThe amount of time that you plan to wait for the results. You can see whatever results you get within this time just like in a normal search. You can poll the remaining results based on an ID. The maximum value is 300 seconds.1 secondNo
keep_on_completionWhether you want to save the results in the cluster after the search is complete. You can examine the stored results at a later time.falseNo
keep_aliveThe amount of time that the result is saved in the cluster. For example, 2d means that the results are stored in the cluster for 48 hours. The saved search results are deleted after this period or if the search is canceled. Note that this includes the query execution time. If the query overruns this time, the process cancels this query automatically.12 hoursNo

Example request

  1. POST _plugins/_asynchronous_search/?pretty&size=10&wait_for_completion_timeout=1ms&keep_on_completion=true&request_cache=false
  2. {
  3. "aggs": {
  4. "city": {
  5. "terms": {
  6. "field": "city",
  7. "size": 10
  8. }
  9. }
  10. }
  11. }

Example response

  1. {
  2. "*id*": "FklfVlU4eFdIUTh1Q1hyM3ZnT19fUVEUd29KLWZYUUI3TzRpdU5wMjRYOHgAAAAAAAAABg==",
  3. "state": "RUNNING",
  4. "start_time_in_millis": 1599833301297,
  5. "expiration_time_in_millis": 1600265301297,
  6. "response": {
  7. "took": 15,
  8. "timed_out": false,
  9. "terminated_early": false,
  10. "num_reduce_phases": 4,
  11. "_shards": {
  12. "total": 21,
  13. "successful": 4,
  14. "skipped": 0,
  15. "failed": 0
  16. },
  17. "hits": {
  18. "total": {
  19. "value": 807,
  20. "relation": "eq"
  21. },
  22. "max_score": null,
  23. "hits": []
  24. },
  25. "aggregations": {
  26. "city": {
  27. "doc_count_error_upper_bound": 16,
  28. "sum_other_doc_count": 403,
  29. "buckets": [
  30. {
  31. "key": "downsville",
  32. "doc_count": 1
  33. },
  34. ....
  35. ....
  36. ....
  37. {
  38. "key": "blairstown",
  39. "doc_count": 1
  40. }
  41. ]
  42. }
  43. }
  44. }
  45. }

Response parameters

OptionsDescription
idThe ID of an asynchronous search. Use this ID to monitor the progress of the search, get its partial results, and/or delete the results. If the asynchronous search finishes within the timeout period, the response doesn’t include the ID because the results aren’t stored in the cluster.
stateSpecifies whether the search is still running or if it has finished, and if the results persist in the cluster. The possible states are RUNNING, COMPLETED, and PERSISTED.
start_time_in_millisThe start time in milliseconds.
expiration_time_in_millisThe expiration time in milliseconds.
tookThe total time that the search is running.
responseThe actual search response.
num_reduce_phasesThe number of times that the coordinating node aggregates results from batches of shard responses (5 by default). If this number increases compared to the last retrieved results, you can expect additional results to be included in the search response.
totalThe total number of shards that run the search.
successfulThe number of shard responses that the coordinating node received successfully.
aggregationsThe partial aggregation results that have been completed by the shards so far.

Get partial results

Introduced 1.0

After you submit an asynchronous search request, you can request partial responses with the ID that you see in the asynchronous search response.

  1. GET _plugins/_asynchronous_search/<ID>?pretty

Example response

  1. {
  2. "id": "Fk9lQk5aWHJIUUltR2xGWnpVcWtFdVEURUN1SWZYUUJBVkFVMEJCTUlZUUoAAAAAAAAAAg==",
  3. "state": "STORE_RESIDENT",
  4. "start_time_in_millis": 1599833907465,
  5. "expiration_time_in_millis": 1600265907465,
  6. "response": {
  7. "took": 83,
  8. "timed_out": false,
  9. "_shards": {
  10. "total": 20,
  11. "successful": 20,
  12. "skipped": 0,
  13. "failed": 0
  14. },
  15. "hits": {
  16. "total": {
  17. "value": 1000,
  18. "relation": "eq"
  19. },
  20. "max_score": 1,
  21. "hits": [
  22. {
  23. "_index": "bank",
  24. "_id": "1",
  25. "_score": 1,
  26. "_source": {
  27. "email": "amberduke@abc.com",
  28. "city": "Brogan",
  29. "state": "IL"
  30. }
  31. },
  32. {....}
  33. ]
  34. },
  35. "aggregations": {
  36. "city": {
  37. "doc_count_error_upper_bound": 0,
  38. "sum_other_doc_count": 997,
  39. "buckets": [
  40. {
  41. "key": "belvoir",
  42. "doc_count": 2
  43. },
  44. {
  45. "key": "aberdeen",
  46. "doc_count": 1
  47. },
  48. {
  49. "key": "abiquiu",
  50. "doc_count": 1
  51. }
  52. ]
  53. }
  54. }
  55. }
  56. }

After the response is successfully persisted, you get back the STORE_RESIDENT state in the response.

You can poll the ID with the wait_for_completion_timeout parameter to wait for the results received for the time that you specify.

For asynchronous searches with keep_on_completion as true and a sufficiently long keep_alive time, you can keep polling the IDs until the search finishes. If you don’t want to periodically poll each ID, you can retain the results in your cluster with the keep_alive parameter and come back to it at a later time.

Delete searches and results

Introduced 1.0

To delete an asynchronous search:

  1. DELETE _plugins/_asynchronous_search/<ID>?pretty
  • If the search is still running, OpenSearch cancels it.
  • If the search is complete, OpenSearch deletes the saved results.

Example response

  1. {
  2. "acknowledged": "true"
  3. }

Monitor stats

Introduced 1.0

You can use the stats API operation to monitor asynchronous searches that are running, completed, and/or persisted.

  1. GET _plugins/_asynchronous_search/stats

Example response

  1. {
  2. "_nodes": {
  3. "total": 8,
  4. "successful": 8,
  5. "failed": 0
  6. },
  7. "cluster_name": "264071961897:asynchronous-search",
  8. "nodes": {
  9. "JKEFl6pdRC-xNkKQauy7Yg": {
  10. "asynchronous_search_stats": {
  11. "submitted": 18236,
  12. "initialized": 112,
  13. "search_failed": 56,
  14. "search_completed": 56,
  15. "rejected": 18124,
  16. "persist_failed": 0,
  17. "cancelled": 1,
  18. "running_current": 399,
  19. "persisted": 100
  20. }
  21. }
  22. }
  23. }

Response parameters

OptionsDescription
submittedThe number of asynchronous search requests that were submitted.
initializedThe number of asynchronous search requests that were initialized.
rejectedThe number of asynchronous search requests that were rejected.
search_completedThe number of asynchronous search requests that completed with a successful response.
search_failedThe number of asynchronous search requests that completed with a failed response.
persistedThe number of asynchronous search requests whose final result successfully persisted in the cluster.
persist_failedThe number of asynchronous search requests whose final result failed to persist in the cluster.
running_currentThe number of asynchronous search requests that are running on a given coordinator node.
cancelledThe number of asynchronous search requests that were canceled while the search was running.