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 ```