github.com/opensearch-project/opensearch-go/v2@v2.3.0/opensearchapi/api.msearch.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 ) 36 37 func newMsearchFunc(t Transport) Msearch { 38 return func(body io.Reader, o ...func(*MsearchRequest)) (*Response, error) { 39 var r = MsearchRequest{Body: body} 40 for _, f := range o { 41 f(&r) 42 } 43 return r.Do(r.ctx, t) 44 } 45 } 46 47 // ----- API Definition ------------------------------------------------------- 48 49 // Msearch allows to execute several search operations in one request. 50 // 51 // 52 type Msearch func(body io.Reader, o ...func(*MsearchRequest)) (*Response, error) 53 54 // MsearchRequest configures the Msearch API request. 55 // 56 type MsearchRequest struct { 57 Index []string 58 59 Body io.Reader 60 61 CcsMinimizeRoundtrips *bool 62 MaxConcurrentSearches *int 63 MaxConcurrentShardRequests *int 64 PreFilterShardSize *int 65 RestTotalHitsAsInt *bool 66 SearchType string 67 TypedKeys *bool 68 69 Pretty bool 70 Human bool 71 ErrorTrace bool 72 FilterPath []string 73 74 Header http.Header 75 76 ctx context.Context 77 } 78 79 // Do executes the request and returns response or error. 80 // 81 func (r MsearchRequest) Do(ctx context.Context, transport Transport) (*Response, error) { 82 var ( 83 method string 84 path strings.Builder 85 params map[string]string 86 ) 87 88 method = "POST" 89 90 path.Grow(1 + len(strings.Join(r.Index, ",")) + 1 + len("_msearch")) 91 if len(r.Index) > 0 { 92 path.WriteString("/") 93 path.WriteString(strings.Join(r.Index, ",")) 94 } 95 path.WriteString("/") 96 path.WriteString("_msearch") 97 98 params = make(map[string]string) 99 100 if r.CcsMinimizeRoundtrips != nil { 101 params["ccs_minimize_roundtrips"] = strconv.FormatBool(*r.CcsMinimizeRoundtrips) 102 } 103 104 if r.MaxConcurrentSearches != nil { 105 params["max_concurrent_searches"] = strconv.FormatInt(int64(*r.MaxConcurrentSearches), 10) 106 } 107 108 if r.MaxConcurrentShardRequests != nil { 109 params["max_concurrent_shard_requests"] = strconv.FormatInt(int64(*r.MaxConcurrentShardRequests), 10) 110 } 111 112 if r.PreFilterShardSize != nil { 113 params["pre_filter_shard_size"] = strconv.FormatInt(int64(*r.PreFilterShardSize), 10) 114 } 115 116 if r.RestTotalHitsAsInt != nil { 117 params["rest_total_hits_as_int"] = strconv.FormatBool(*r.RestTotalHitsAsInt) 118 } 119 120 if r.SearchType != "" { 121 params["search_type"] = r.SearchType 122 } 123 124 if r.TypedKeys != nil { 125 params["typed_keys"] = strconv.FormatBool(*r.TypedKeys) 126 } 127 128 if r.Pretty { 129 params["pretty"] = "true" 130 } 131 132 if r.Human { 133 params["human"] = "true" 134 } 135 136 if r.ErrorTrace { 137 params["error_trace"] = "true" 138 } 139 140 if len(r.FilterPath) > 0 { 141 params["filter_path"] = strings.Join(r.FilterPath, ",") 142 } 143 144 req, err := newRequest(method, path.String(), r.Body) 145 if err != nil { 146 return nil, err 147 } 148 149 if len(params) > 0 { 150 q := req.URL.Query() 151 for k, v := range params { 152 q.Set(k, v) 153 } 154 req.URL.RawQuery = q.Encode() 155 } 156 157 if r.Body != nil { 158 req.Header[headerContentType] = headerContentTypeJSON 159 } 160 161 if len(r.Header) > 0 { 162 if len(req.Header) == 0 { 163 req.Header = r.Header 164 } else { 165 for k, vv := range r.Header { 166 for _, v := range vv { 167 req.Header.Add(k, v) 168 } 169 } 170 } 171 } 172 173 if ctx != nil { 174 req = req.WithContext(ctx) 175 } 176 177 res, err := transport.Perform(req) 178 if err != nil { 179 return nil, err 180 } 181 182 response := Response{ 183 StatusCode: res.StatusCode, 184 Body: res.Body, 185 Header: res.Header, 186 } 187 188 return &response, nil 189 } 190 191 // WithContext sets the request context. 192 // 193 func (f Msearch) WithContext(v context.Context) func(*MsearchRequest) { 194 return func(r *MsearchRequest) { 195 r.ctx = v 196 } 197 } 198 199 // WithIndex - a list of index names to use as default. 200 // 201 func (f Msearch) WithIndex(v ...string) func(*MsearchRequest) { 202 return func(r *MsearchRequest) { 203 r.Index = v 204 } 205 } 206 207 // WithCcsMinimizeRoundtrips - indicates whether network round-trips should be minimized as part of cross-cluster search requests execution. 208 // 209 func (f Msearch) WithCcsMinimizeRoundtrips(v bool) func(*MsearchRequest) { 210 return func(r *MsearchRequest) { 211 r.CcsMinimizeRoundtrips = &v 212 } 213 } 214 215 // WithMaxConcurrentSearches - controls the maximum number of concurrent searches the multi search api will execute. 216 // 217 func (f Msearch) WithMaxConcurrentSearches(v int) func(*MsearchRequest) { 218 return func(r *MsearchRequest) { 219 r.MaxConcurrentSearches = &v 220 } 221 } 222 223 // WithMaxConcurrentShardRequests - the number of concurrent shard requests each sub search executes concurrently per node. this value should be used to limit the impact of the search on the cluster in order to limit the number of concurrent shard requests. 224 // 225 func (f Msearch) WithMaxConcurrentShardRequests(v int) func(*MsearchRequest) { 226 return func(r *MsearchRequest) { 227 r.MaxConcurrentShardRequests = &v 228 } 229 } 230 231 // WithPreFilterShardSize - a threshold that enforces a pre-filter roundtrip to prefilter search shards based on query rewriting if the number of shards the search request expands to exceeds the threshold. this filter roundtrip can limit the number of shards significantly if for instance a shard can not match any documents based on its rewrite method ie. if date filters are mandatory to match but the shard bounds and the query are disjoint.. 232 // 233 func (f Msearch) WithPreFilterShardSize(v int) func(*MsearchRequest) { 234 return func(r *MsearchRequest) { 235 r.PreFilterShardSize = &v 236 } 237 } 238 239 // WithRestTotalHitsAsInt - indicates whether hits.total should be rendered as an integer or an object in the rest search response. 240 // 241 func (f Msearch) WithRestTotalHitsAsInt(v bool) func(*MsearchRequest) { 242 return func(r *MsearchRequest) { 243 r.RestTotalHitsAsInt = &v 244 } 245 } 246 247 // WithSearchType - search operation type. 248 // 249 func (f Msearch) WithSearchType(v string) func(*MsearchRequest) { 250 return func(r *MsearchRequest) { 251 r.SearchType = v 252 } 253 } 254 255 // WithTypedKeys - specify whether aggregation and suggester names should be prefixed by their respective types in the response. 256 // 257 func (f Msearch) WithTypedKeys(v bool) func(*MsearchRequest) { 258 return func(r *MsearchRequest) { 259 r.TypedKeys = &v 260 } 261 } 262 263 // WithPretty makes the response body pretty-printed. 264 // 265 func (f Msearch) WithPretty() func(*MsearchRequest) { 266 return func(r *MsearchRequest) { 267 r.Pretty = true 268 } 269 } 270 271 // WithHuman makes statistical values human-readable. 272 // 273 func (f Msearch) WithHuman() func(*MsearchRequest) { 274 return func(r *MsearchRequest) { 275 r.Human = true 276 } 277 } 278 279 // WithErrorTrace includes the stack trace for errors in the response body. 280 // 281 func (f Msearch) WithErrorTrace() func(*MsearchRequest) { 282 return func(r *MsearchRequest) { 283 r.ErrorTrace = true 284 } 285 } 286 287 // WithFilterPath filters the properties of the response body. 288 // 289 func (f Msearch) WithFilterPath(v ...string) func(*MsearchRequest) { 290 return func(r *MsearchRequest) { 291 r.FilterPath = v 292 } 293 } 294 295 // WithHeader adds the headers to the HTTP request. 296 // 297 func (f Msearch) WithHeader(h map[string]string) func(*MsearchRequest) { 298 return func(r *MsearchRequest) { 299 if r.Header == nil { 300 r.Header = make(http.Header) 301 } 302 for k, v := range h { 303 r.Header.Add(k, v) 304 } 305 } 306 } 307 308 // WithOpaqueID adds the X-Opaque-Id header to the HTTP request. 309 // 310 func (f Msearch) WithOpaqueID(s string) func(*MsearchRequest) { 311 return func(r *MsearchRequest) { 312 if r.Header == nil { 313 r.Header = make(http.Header) 314 } 315 r.Header.Set("X-Opaque-Id", s) 316 } 317 }