github.com/opensearch-project/opensearch-go/v2@v2.3.0/opensearchapi/api.search_template.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // 3 // The OpenSearch Contributors require contributions made to 4 // this file be licensed under the Apache-2.0 license or a 5 // compatible open source license. 6 // 7 // Modifications Copyright OpenSearch Contributors. See 8 // GitHub history for details. 9 10 // Licensed to Elasticsearch B.V. under one or more contributor 11 // license agreements. See the NOTICE file distributed with 12 // this work for additional information regarding copyright 13 // ownership. Elasticsearch B.V. licenses this file to you under 14 // the Apache License, Version 2.0 (the "License"); you may 15 // not use this file except in compliance with the License. 16 // You may obtain a copy of the License at 17 // 18 // http://www.apache.org/licenses/LICENSE-2.0 19 // 20 // Unless required by applicable law or agreed to in writing, 21 // software distributed under the License is distributed on an 22 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 23 // KIND, either express or implied. See the License for the 24 // specific language governing permissions and limitations 25 // under the License. 26 27 package opensearchapi 28 29 import ( 30 "context" 31 "io" 32 "net/http" 33 "strconv" 34 "strings" 35 "time" 36 ) 37 38 func newSearchTemplateFunc(t Transport) SearchTemplate { 39 return func(body io.Reader, o ...func(*SearchTemplateRequest)) (*Response, error) { 40 var r = SearchTemplateRequest{Body: body} 41 for _, f := range o { 42 f(&r) 43 } 44 return r.Do(r.ctx, t) 45 } 46 } 47 48 // ----- API Definition ------------------------------------------------------- 49 50 // SearchTemplate allows to use the Mustache language to pre-render a search definition. 51 // 52 // 53 type SearchTemplate func(body io.Reader, o ...func(*SearchTemplateRequest)) (*Response, error) 54 55 // SearchTemplateRequest configures the Search Template API request. 56 // 57 type SearchTemplateRequest struct { 58 Index []string 59 60 Body io.Reader 61 62 AllowNoIndices *bool 63 CcsMinimizeRoundtrips *bool 64 ExpandWildcards string 65 Explain *bool 66 IgnoreThrottled *bool 67 IgnoreUnavailable *bool 68 Preference string 69 Profile *bool 70 RestTotalHitsAsInt *bool 71 Routing []string 72 Scroll time.Duration 73 SearchType string 74 TypedKeys *bool 75 76 Pretty bool 77 Human bool 78 ErrorTrace bool 79 FilterPath []string 80 81 Header http.Header 82 83 ctx context.Context 84 } 85 86 // Do executes the request and returns response or error. 87 // 88 func (r SearchTemplateRequest) Do(ctx context.Context, transport Transport) (*Response, error) { 89 var ( 90 method string 91 path strings.Builder 92 params map[string]string 93 ) 94 95 method = "POST" 96 97 path.Grow(1 + len(strings.Join(r.Index, ",")) + 1 + len("_search") + 1 + len("template")) 98 if len(r.Index) > 0 { 99 path.WriteString("/") 100 path.WriteString(strings.Join(r.Index, ",")) 101 } 102 path.WriteString("/") 103 path.WriteString("_search") 104 path.WriteString("/") 105 path.WriteString("template") 106 107 params = make(map[string]string) 108 109 if r.AllowNoIndices != nil { 110 params["allow_no_indices"] = strconv.FormatBool(*r.AllowNoIndices) 111 } 112 113 if r.CcsMinimizeRoundtrips != nil { 114 params["ccs_minimize_roundtrips"] = strconv.FormatBool(*r.CcsMinimizeRoundtrips) 115 } 116 117 if r.ExpandWildcards != "" { 118 params["expand_wildcards"] = r.ExpandWildcards 119 } 120 121 if r.Explain != nil { 122 params["explain"] = strconv.FormatBool(*r.Explain) 123 } 124 125 if r.IgnoreThrottled != nil { 126 params["ignore_throttled"] = strconv.FormatBool(*r.IgnoreThrottled) 127 } 128 129 if r.IgnoreUnavailable != nil { 130 params["ignore_unavailable"] = strconv.FormatBool(*r.IgnoreUnavailable) 131 } 132 133 if r.Preference != "" { 134 params["preference"] = r.Preference 135 } 136 137 if r.Profile != nil { 138 params["profile"] = strconv.FormatBool(*r.Profile) 139 } 140 141 if r.RestTotalHitsAsInt != nil { 142 params["rest_total_hits_as_int"] = strconv.FormatBool(*r.RestTotalHitsAsInt) 143 } 144 145 if len(r.Routing) > 0 { 146 params["routing"] = strings.Join(r.Routing, ",") 147 } 148 149 if r.Scroll != 0 { 150 params["scroll"] = formatDuration(r.Scroll) 151 } 152 153 if r.SearchType != "" { 154 params["search_type"] = r.SearchType 155 } 156 157 if r.TypedKeys != nil { 158 params["typed_keys"] = strconv.FormatBool(*r.TypedKeys) 159 } 160 161 if r.Pretty { 162 params["pretty"] = "true" 163 } 164 165 if r.Human { 166 params["human"] = "true" 167 } 168 169 if r.ErrorTrace { 170 params["error_trace"] = "true" 171 } 172 173 if len(r.FilterPath) > 0 { 174 params["filter_path"] = strings.Join(r.FilterPath, ",") 175 } 176 177 req, err := newRequest(method, path.String(), r.Body) 178 if err != nil { 179 return nil, err 180 } 181 182 if len(params) > 0 { 183 q := req.URL.Query() 184 for k, v := range params { 185 q.Set(k, v) 186 } 187 req.URL.RawQuery = q.Encode() 188 } 189 190 if r.Body != nil { 191 req.Header[headerContentType] = headerContentTypeJSON 192 } 193 194 if len(r.Header) > 0 { 195 if len(req.Header) == 0 { 196 req.Header = r.Header 197 } else { 198 for k, vv := range r.Header { 199 for _, v := range vv { 200 req.Header.Add(k, v) 201 } 202 } 203 } 204 } 205 206 if ctx != nil { 207 req = req.WithContext(ctx) 208 } 209 210 res, err := transport.Perform(req) 211 if err != nil { 212 return nil, err 213 } 214 215 response := Response{ 216 StatusCode: res.StatusCode, 217 Body: res.Body, 218 Header: res.Header, 219 } 220 221 return &response, nil 222 } 223 224 // WithContext sets the request context. 225 // 226 func (f SearchTemplate) WithContext(v context.Context) func(*SearchTemplateRequest) { 227 return func(r *SearchTemplateRequest) { 228 r.ctx = v 229 } 230 } 231 232 // WithIndex - a list of index names to search; use _all to perform the operation on all indices. 233 // 234 func (f SearchTemplate) WithIndex(v ...string) func(*SearchTemplateRequest) { 235 return func(r *SearchTemplateRequest) { 236 r.Index = v 237 } 238 } 239 240 // WithAllowNoIndices - whether to ignore if a wildcard indices expression resolves into no concrete indices. (this includes `_all` string or when no indices have been specified). 241 // 242 func (f SearchTemplate) WithAllowNoIndices(v bool) func(*SearchTemplateRequest) { 243 return func(r *SearchTemplateRequest) { 244 r.AllowNoIndices = &v 245 } 246 } 247 248 // WithCcsMinimizeRoundtrips - indicates whether network round-trips should be minimized as part of cross-cluster search requests execution. 249 // 250 func (f SearchTemplate) WithCcsMinimizeRoundtrips(v bool) func(*SearchTemplateRequest) { 251 return func(r *SearchTemplateRequest) { 252 r.CcsMinimizeRoundtrips = &v 253 } 254 } 255 256 // WithExpandWildcards - whether to expand wildcard expression to concrete indices that are open, closed or both.. 257 // 258 func (f SearchTemplate) WithExpandWildcards(v string) func(*SearchTemplateRequest) { 259 return func(r *SearchTemplateRequest) { 260 r.ExpandWildcards = v 261 } 262 } 263 264 // WithExplain - specify whether to return detailed information about score computation as part of a hit. 265 // 266 func (f SearchTemplate) WithExplain(v bool) func(*SearchTemplateRequest) { 267 return func(r *SearchTemplateRequest) { 268 r.Explain = &v 269 } 270 } 271 272 // WithIgnoreThrottled - whether specified concrete, expanded or aliased indices should be ignored when throttled. 273 // 274 func (f SearchTemplate) WithIgnoreThrottled(v bool) func(*SearchTemplateRequest) { 275 return func(r *SearchTemplateRequest) { 276 r.IgnoreThrottled = &v 277 } 278 } 279 280 // WithIgnoreUnavailable - whether specified concrete indices should be ignored when unavailable (missing or closed). 281 // 282 func (f SearchTemplate) WithIgnoreUnavailable(v bool) func(*SearchTemplateRequest) { 283 return func(r *SearchTemplateRequest) { 284 r.IgnoreUnavailable = &v 285 } 286 } 287 288 // WithPreference - specify the node or shard the operation should be performed on (default: random). 289 // 290 func (f SearchTemplate) WithPreference(v string) func(*SearchTemplateRequest) { 291 return func(r *SearchTemplateRequest) { 292 r.Preference = v 293 } 294 } 295 296 // WithProfile - specify whether to profile the query execution. 297 // 298 func (f SearchTemplate) WithProfile(v bool) func(*SearchTemplateRequest) { 299 return func(r *SearchTemplateRequest) { 300 r.Profile = &v 301 } 302 } 303 304 // WithRestTotalHitsAsInt - indicates whether hits.total should be rendered as an integer or an object in the rest search response. 305 // 306 func (f SearchTemplate) WithRestTotalHitsAsInt(v bool) func(*SearchTemplateRequest) { 307 return func(r *SearchTemplateRequest) { 308 r.RestTotalHitsAsInt = &v 309 } 310 } 311 312 // WithRouting - a list of specific routing values. 313 // 314 func (f SearchTemplate) WithRouting(v ...string) func(*SearchTemplateRequest) { 315 return func(r *SearchTemplateRequest) { 316 r.Routing = v 317 } 318 } 319 320 // WithScroll - specify how long a consistent view of the index should be maintained for scrolled search. 321 // 322 func (f SearchTemplate) WithScroll(v time.Duration) func(*SearchTemplateRequest) { 323 return func(r *SearchTemplateRequest) { 324 r.Scroll = v 325 } 326 } 327 328 // WithSearchType - search operation type. 329 // 330 func (f SearchTemplate) WithSearchType(v string) func(*SearchTemplateRequest) { 331 return func(r *SearchTemplateRequest) { 332 r.SearchType = v 333 } 334 } 335 336 // WithTypedKeys - specify whether aggregation and suggester names should be prefixed by their respective types in the response. 337 // 338 func (f SearchTemplate) WithTypedKeys(v bool) func(*SearchTemplateRequest) { 339 return func(r *SearchTemplateRequest) { 340 r.TypedKeys = &v 341 } 342 } 343 344 // WithPretty makes the response body pretty-printed. 345 // 346 func (f SearchTemplate) WithPretty() func(*SearchTemplateRequest) { 347 return func(r *SearchTemplateRequest) { 348 r.Pretty = true 349 } 350 } 351 352 // WithHuman makes statistical values human-readable. 353 // 354 func (f SearchTemplate) WithHuman() func(*SearchTemplateRequest) { 355 return func(r *SearchTemplateRequest) { 356 r.Human = true 357 } 358 } 359 360 // WithErrorTrace includes the stack trace for errors in the response body. 361 // 362 func (f SearchTemplate) WithErrorTrace() func(*SearchTemplateRequest) { 363 return func(r *SearchTemplateRequest) { 364 r.ErrorTrace = true 365 } 366 } 367 368 // WithFilterPath filters the properties of the response body. 369 // 370 func (f SearchTemplate) WithFilterPath(v ...string) func(*SearchTemplateRequest) { 371 return func(r *SearchTemplateRequest) { 372 r.FilterPath = v 373 } 374 } 375 376 // WithHeader adds the headers to the HTTP request. 377 // 378 func (f SearchTemplate) WithHeader(h map[string]string) func(*SearchTemplateRequest) { 379 return func(r *SearchTemplateRequest) { 380 if r.Header == nil { 381 r.Header = make(http.Header) 382 } 383 for k, v := range h { 384 r.Header.Add(k, v) 385 } 386 } 387 } 388 389 // WithOpaqueID adds the X-Opaque-Id header to the HTTP request. 390 // 391 func (f SearchTemplate) WithOpaqueID(s string) func(*SearchTemplateRequest) { 392 return func(r *SearchTemplateRequest) { 393 if r.Header == nil { 394 r.Header = make(http.Header) 395 } 396 r.Header.Set("X-Opaque-Id", s) 397 } 398 }