github.com/opensearch-project/opensearch-go/v2@v2.3.0/guides/search.md (about)

     1  # Search
     2  
     3  OpenSearch provides a powerful search API that allows you to search for documents in an index. The search API supports a number of parameters that allow you to customize the search operation. In this guide, we will explore the search API and its parameters.
     4  
     5  # Setup
     6  
     7  Let's start by creating an index and adding some documents to it:
     8  
     9  ```go
    10  package main
    11  
    12  import (
    13      "context"
    14      "fmt"
    15      "github.com/opensearch-project/opensearch-go/v2"
    16      "github.com/opensearch-project/opensearch-go/v2/opensearchapi"
    17      "log"
    18      "strings"
    19  )
    20  
    21  func main() {
    22      client, err := opensearch.NewDefaultClient()
    23      if err != nil {
    24          log.Printf("error occurred: [%s]", err.Error())
    25      }
    26      log.Printf("response: [%+v]", client)
    27  
    28      movies := "movies"
    29  
    30      // create the index
    31      createMovieIndex, err := client.Indices.Create(movies)
    32      if err != nil {
    33          log.Printf("error occurred: [%s]", err.Error())
    34      }
    35      log.Printf("response: [%+v]", createMovieIndex)
    36  
    37      for i := 1; i < 11; i++ {
    38          req := opensearchapi.IndexRequest{
    39              Index:      movies,
    40              DocumentID: fmt.Sprintf("%d", i),
    41              Body:       strings.NewReader(fmt.Sprintf(`{"title": "The Dark Knight %d", "director": "Christopher Nolan", "year": %d}`, i, 2008+i)),
    42          }
    43          _, err := req.Do(context.Background(), client)
    44          if err != nil {
    45              log.Printf("error occurred: [%s]", err.Error())
    46          }
    47      }
    48  
    49      req := opensearchapi.IndexRequest{
    50          Index: movies,
    51          Body:  strings.NewReader(`{"title": "The Godfather", "director": "Francis Ford Coppola", "year": 1972}`),
    52      }
    53      _, err = req.Do(context.Background(), client)
    54      if err != nil {
    55          log.Printf("error occurred: [%s]", err.Error())
    56      }
    57  
    58      req = opensearchapi.IndexRequest{
    59          Index: movies,
    60          Body:  strings.NewReader(`{"title": "The Shawshank Redemption", "director": "Frank Darabont", "year": 1994}`),
    61      }
    62      _, err = req.Do(context.Background(), client)
    63      if err != nil {
    64          log.Printf("error occurred: [%s]", err.Error())
    65      }
    66  
    67      // refresh the index to make the documents searchable
    68      _, err = client.Indices.Refresh(client.Indices.Refresh.WithIndex(movies))
    69      if err != nil {
    70          log.Printf("error occurred: [%s]", err.Error())
    71      }
    72  }
    73  ```
    74  
    75  ## Search API
    76  
    77  ### Basic Search
    78  
    79  The search API allows you to search for documents in an index. The following example searches for ALL documents in the `movies` index:
    80  
    81  ```go
    82  res, err := client.Search(
    83      client.Search.WithIndex(movies),
    84  )
    85  if err != nil {
    86      log.Printf("error occurred: [%s]", err.Error())
    87  }
    88  log.Printf("response: [%+v]", res)
    89  ```
    90  
    91  You can also search for documents that match a specific query. The following example searches for documents that match the query `dark knight`:
    92  
    93  ```go
    94  part, err := client.Search(
    95      client.Search.WithIndex(movies),
    96      client.Search.WithQuery(`title: "dark knight"`),
    97  )
    98  if err != nil {
    99      log.Printf("error occurred: [%s]", err.Error())
   100  }
   101  log.Printf("response: [%+v]", part)
   102  ```
   103  
   104  OpenSearch query DSL allows you to specify complex queries. Check out the [OpenSearch query DSL documentation](https://opensearch.org/docs/latest/query-dsl/) for more information.
   105  
   106  ### Basic Pagination
   107  
   108  The search API allows you to paginate through the search results. The following example searches for documents that match the query `dark knight`, sorted by `year` in ascending order, and returns the first 2 results after skipping the first 5 results:
   109  
   110  ```go
   111  sort, err := client.Search(
   112      client.Search.WithIndex(movies),
   113      client.Search.WithSize(2),
   114      client.Search.WithFrom(5),
   115      client.Search.WithSort("year:desc"),
   116      client.Search.WithQuery(`title: "dark knight"`),
   117  )
   118  if err != nil {
   119      log.Printf("error occurred: [%s]", err.Error())
   120  }
   121  log.Printf("response: [%+v]", sort)
   122  ```
   123  
   124  ### Pagination with scroll
   125  
   126  When retrieving large amounts of non-real-time data, you can use the `scroll` parameter to paginate through the search results.
   127  
   128  ```go
   129  page1, err := client.Search(
   130      client.Search.WithIndex(movies),
   131      client.Search.WithSize(2),
   132      client.Search.WithQuery(`title: "dark knight"`),
   133      client.Search.WithSort("year:asc"),
   134      client.Search.WithScroll(time.Minute),
   135  )
   136  if err != nil {
   137      log.Printf("error occurred: [%s]", err.Error())
   138  }
   139  log.Printf("response: [%+v]", page1)
   140  ```
   141  
   142  ### Pagination with Point in Time
   143  
   144  The scroll example above has one weakness: if the index is updated while you are scrolling through the results, they will be paginated inconsistently. To avoid this, you should use the "Point in Time" feature. The following example demonstrates how to use the `point_in_time` and `pit_id` parameters to paginate through the search results:
   145  
   146  ```go
   147  // create a point in time
   148  _, pit, err := client.PointInTime.Create(
   149      client.PointInTime.Create.WithIndex(movies),
   150      client.PointInTime.Create.WithKeepAlive(time.Minute),
   151  )
   152  if err != nil {
   153      log.Printf("error occurred: [%s]", err.Error())
   154  }
   155  log.Printf("created pit: [%+v]", pit)
   156  
   157  // run a search query with a pit.id
   158  page1, err := client.Search(
   159      client.Search.WithSize(5),
   160      client.Search.WithBody(strings.NewReader(fmt.Sprintf(`{ "pit": { "id": "%s", "keep_alive": "1m" } }`, pit.PitID))),
   161      client.Search.WithSort("year:asc"),
   162  )
   163  if err != nil {
   164      log.Printf("error occurred: [%s]", err.Error())
   165  }
   166  log.Printf("response: [%+v]", page1)
   167  
   168  // to get the next set of documents, run the same query with the last document’s sort values as the search_after parameter, keeping the same sort and pit.id.
   169  page2, err := client.Search(
   170      client.Search.WithSize(5),
   171      client.Search.WithBody(strings.NewReader(fmt.Sprintf(`{ "pit": { "id": "%s", "keep_alive": "1m" }, "search_after": [ "1994" ] }`, pit.PitID))),
   172      client.Search.WithSort("year:asc"),
   173  )
   174  if err != nil {
   175      log.Printf("error occurred: [%s]", err.Error())
   176  }
   177  log.Printf("response: [%+v]", page2)
   178  
   179  // to delete the point in time, run the following query
   180  _, delpits, err := client.PointInTime.Delete(client.PointInTime.Delete.WithPitID(pit.PitID))
   181  if err != nil {
   182      log.Printf("error occurred: [%s]", err.Error())
   183  }
   184  log.Printf("deleted pits: [%+v]", delpits)
   185  ```
   186  
   187  Note that a point-in-time is associated with an index or a set of index. So, when performing a search with a point-in-time, you DO NOT specify the index in the search.
   188  
   189  ## Cleanup
   190  
   191  ```go
   192  deleteIndex, err := client.Indices.Delete([]string{"movies"})
   193  if err != nil {
   194      log.Printf("Error creating index: %s", err.Error())
   195  }
   196  log.Printf("response: [%+v]", deleteIndex)
   197  ```