github.com/opensearch-project/opensearch-go/v2@v2.3.0/opensearchapi/api.search.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  	"fmt"
    32  	"io"
    33  	"net/http"
    34  	"strconv"
    35  	"strings"
    36  	"time"
    37  )
    38  
    39  func newSearchFunc(t Transport) Search {
    40  	return func(o ...func(*SearchRequest)) (*Response, error) {
    41  		var r = SearchRequest{}
    42  		for _, f := range o {
    43  			f(&r)
    44  		}
    45  		return r.Do(r.ctx, t)
    46  	}
    47  }
    48  
    49  // ----- API Definition -------------------------------------------------------
    50  
    51  // Search returns results matching a query.
    52  //
    53  //
    54  type Search func(o ...func(*SearchRequest)) (*Response, error)
    55  
    56  // SearchRequest configures the Search API request.
    57  //
    58  type SearchRequest struct {
    59  	Index []string
    60  
    61  	Body io.Reader
    62  
    63  	AllowNoIndices             *bool
    64  	AllowPartialSearchResults  *bool
    65  	Analyzer                   string
    66  	AnalyzeWildcard            *bool
    67  	BatchedReduceSize          *int
    68  	CcsMinimizeRoundtrips      *bool
    69  	DefaultOperator            string
    70  	Df                         string
    71  	DocvalueFields             []string
    72  	ExpandWildcards            string
    73  	Explain                    *bool
    74  	From                       *int
    75  	IgnoreThrottled            *bool
    76  	IgnoreUnavailable          *bool
    77  	Lenient                    *bool
    78  	MaxConcurrentShardRequests *int
    79  	MinCompatibleShardNode     string
    80  	Preference                 string
    81  	PreFilterShardSize         *int
    82  	Query                      string
    83  	RequestCache               *bool
    84  	RestTotalHitsAsInt         *bool
    85  	Routing                    []string
    86  	Scroll                     time.Duration
    87  	SearchType                 string
    88  	SeqNoPrimaryTerm           *bool
    89  	Size                       *int
    90  	Sort                       []string
    91  	Source                     interface{}
    92  	SourceExcludes             []string
    93  	SourceIncludes             []string
    94  	Stats                      []string
    95  	StoredFields               []string
    96  	SuggestField               string
    97  	SuggestMode                string
    98  	SuggestSize                *int
    99  	SuggestText                string
   100  	TerminateAfter             *int
   101  	Timeout                    time.Duration
   102  	TrackScores                *bool
   103  	TrackTotalHits             interface{}
   104  	TypedKeys                  *bool
   105  	Version                    *bool
   106  
   107  	Pretty     bool
   108  	Human      bool
   109  	ErrorTrace bool
   110  	FilterPath []string
   111  
   112  	Header http.Header
   113  
   114  	ctx context.Context
   115  }
   116  
   117  // Do executes the request and returns response or error.
   118  //
   119  func (r SearchRequest) Do(ctx context.Context, transport Transport) (*Response, error) {
   120  	var (
   121  		method string
   122  		path   strings.Builder
   123  		params map[string]string
   124  	)
   125  
   126  	method = "POST"
   127  
   128  	path.Grow(1 + len(strings.Join(r.Index, ",")) + 1 + len("_search"))
   129  	if len(r.Index) > 0 {
   130  		path.WriteString("/")
   131  		path.WriteString(strings.Join(r.Index, ","))
   132  	}
   133  	path.WriteString("/")
   134  	path.WriteString("_search")
   135  
   136  	params = make(map[string]string)
   137  
   138  	if r.AllowNoIndices != nil {
   139  		params["allow_no_indices"] = strconv.FormatBool(*r.AllowNoIndices)
   140  	}
   141  
   142  	if r.AllowPartialSearchResults != nil {
   143  		params["allow_partial_search_results"] = strconv.FormatBool(*r.AllowPartialSearchResults)
   144  	}
   145  
   146  	if r.Analyzer != "" {
   147  		params["analyzer"] = r.Analyzer
   148  	}
   149  
   150  	if r.AnalyzeWildcard != nil {
   151  		params["analyze_wildcard"] = strconv.FormatBool(*r.AnalyzeWildcard)
   152  	}
   153  
   154  	if r.BatchedReduceSize != nil {
   155  		params["batched_reduce_size"] = strconv.FormatInt(int64(*r.BatchedReduceSize), 10)
   156  	}
   157  
   158  	if r.CcsMinimizeRoundtrips != nil {
   159  		params["ccs_minimize_roundtrips"] = strconv.FormatBool(*r.CcsMinimizeRoundtrips)
   160  	}
   161  
   162  	if r.DefaultOperator != "" {
   163  		params["default_operator"] = r.DefaultOperator
   164  	}
   165  
   166  	if r.Df != "" {
   167  		params["df"] = r.Df
   168  	}
   169  
   170  	if len(r.DocvalueFields) > 0 {
   171  		params["docvalue_fields"] = strings.Join(r.DocvalueFields, ",")
   172  	}
   173  
   174  	if r.ExpandWildcards != "" {
   175  		params["expand_wildcards"] = r.ExpandWildcards
   176  	}
   177  
   178  	if r.Explain != nil {
   179  		params["explain"] = strconv.FormatBool(*r.Explain)
   180  	}
   181  
   182  	if r.From != nil {
   183  		params["from"] = strconv.FormatInt(int64(*r.From), 10)
   184  	}
   185  
   186  	if r.IgnoreThrottled != nil {
   187  		params["ignore_throttled"] = strconv.FormatBool(*r.IgnoreThrottled)
   188  	}
   189  
   190  	if r.IgnoreUnavailable != nil {
   191  		params["ignore_unavailable"] = strconv.FormatBool(*r.IgnoreUnavailable)
   192  	}
   193  
   194  	if r.Lenient != nil {
   195  		params["lenient"] = strconv.FormatBool(*r.Lenient)
   196  	}
   197  
   198  	if r.MaxConcurrentShardRequests != nil {
   199  		params["max_concurrent_shard_requests"] = strconv.FormatInt(int64(*r.MaxConcurrentShardRequests), 10)
   200  	}
   201  
   202  	if r.MinCompatibleShardNode != "" {
   203  		params["min_compatible_shard_node"] = r.MinCompatibleShardNode
   204  	}
   205  
   206  	if r.Preference != "" {
   207  		params["preference"] = r.Preference
   208  	}
   209  
   210  	if r.PreFilterShardSize != nil {
   211  		params["pre_filter_shard_size"] = strconv.FormatInt(int64(*r.PreFilterShardSize), 10)
   212  	}
   213  
   214  	if r.Query != "" {
   215  		params["q"] = r.Query
   216  	}
   217  
   218  	if r.RequestCache != nil {
   219  		params["request_cache"] = strconv.FormatBool(*r.RequestCache)
   220  	}
   221  
   222  	if r.RestTotalHitsAsInt != nil {
   223  		params["rest_total_hits_as_int"] = strconv.FormatBool(*r.RestTotalHitsAsInt)
   224  	}
   225  
   226  	if len(r.Routing) > 0 {
   227  		params["routing"] = strings.Join(r.Routing, ",")
   228  	}
   229  
   230  	if r.Scroll != 0 {
   231  		params["scroll"] = formatDuration(r.Scroll)
   232  	}
   233  
   234  	if r.SearchType != "" {
   235  		params["search_type"] = r.SearchType
   236  	}
   237  
   238  	if r.SeqNoPrimaryTerm != nil {
   239  		params["seq_no_primary_term"] = strconv.FormatBool(*r.SeqNoPrimaryTerm)
   240  	}
   241  
   242  	if r.Size != nil {
   243  		params["size"] = strconv.FormatInt(int64(*r.Size), 10)
   244  	}
   245  
   246  	if len(r.Sort) > 0 {
   247  		params["sort"] = strings.Join(r.Sort, ",")
   248  	}
   249  
   250  	if source, ok := r.Source.(bool); ok {
   251  		params["_source"] = strconv.FormatBool(source)
   252  	} else if source, ok := r.Source.(string); ok && source != "" {
   253  		params["_source"] = source
   254  	} else if sources, ok := r.Source.([]string); ok && len(sources) > 0 {
   255  		params["_source"] = strings.Join(sources, ",")
   256  	}
   257  
   258  	if len(r.SourceExcludes) > 0 {
   259  		params["_source_excludes"] = strings.Join(r.SourceExcludes, ",")
   260  	}
   261  
   262  	if len(r.SourceIncludes) > 0 {
   263  		params["_source_includes"] = strings.Join(r.SourceIncludes, ",")
   264  	}
   265  
   266  	if len(r.Stats) > 0 {
   267  		params["stats"] = strings.Join(r.Stats, ",")
   268  	}
   269  
   270  	if len(r.StoredFields) > 0 {
   271  		params["stored_fields"] = strings.Join(r.StoredFields, ",")
   272  	}
   273  
   274  	if r.SuggestField != "" {
   275  		params["suggest_field"] = r.SuggestField
   276  	}
   277  
   278  	if r.SuggestMode != "" {
   279  		params["suggest_mode"] = r.SuggestMode
   280  	}
   281  
   282  	if r.SuggestSize != nil {
   283  		params["suggest_size"] = strconv.FormatInt(int64(*r.SuggestSize), 10)
   284  	}
   285  
   286  	if r.SuggestText != "" {
   287  		params["suggest_text"] = r.SuggestText
   288  	}
   289  
   290  	if r.TerminateAfter != nil {
   291  		params["terminate_after"] = strconv.FormatInt(int64(*r.TerminateAfter), 10)
   292  	}
   293  
   294  	if r.Timeout != 0 {
   295  		params["timeout"] = formatDuration(r.Timeout)
   296  	}
   297  
   298  	if r.TrackScores != nil {
   299  		params["track_scores"] = strconv.FormatBool(*r.TrackScores)
   300  	}
   301  
   302  	if r.TrackTotalHits != nil {
   303  		params["track_total_hits"] = fmt.Sprintf("%v", r.TrackTotalHits)
   304  	}
   305  
   306  	if r.TypedKeys != nil {
   307  		params["typed_keys"] = strconv.FormatBool(*r.TypedKeys)
   308  	}
   309  
   310  	if r.Version != nil {
   311  		params["version"] = strconv.FormatBool(*r.Version)
   312  	}
   313  
   314  	if r.Pretty {
   315  		params["pretty"] = "true"
   316  	}
   317  
   318  	if r.Human {
   319  		params["human"] = "true"
   320  	}
   321  
   322  	if r.ErrorTrace {
   323  		params["error_trace"] = "true"
   324  	}
   325  
   326  	if len(r.FilterPath) > 0 {
   327  		params["filter_path"] = strings.Join(r.FilterPath, ",")
   328  	}
   329  
   330  	req, err := newRequest(method, path.String(), r.Body)
   331  	if err != nil {
   332  		return nil, err
   333  	}
   334  
   335  	if len(params) > 0 {
   336  		q := req.URL.Query()
   337  		for k, v := range params {
   338  			q.Set(k, v)
   339  		}
   340  		req.URL.RawQuery = q.Encode()
   341  	}
   342  
   343  	if r.Body != nil {
   344  		req.Header[headerContentType] = headerContentTypeJSON
   345  	}
   346  
   347  	if len(r.Header) > 0 {
   348  		if len(req.Header) == 0 {
   349  			req.Header = r.Header
   350  		} else {
   351  			for k, vv := range r.Header {
   352  				for _, v := range vv {
   353  					req.Header.Add(k, v)
   354  				}
   355  			}
   356  		}
   357  	}
   358  
   359  	if ctx != nil {
   360  		req = req.WithContext(ctx)
   361  	}
   362  
   363  	res, err := transport.Perform(req)
   364  	if err != nil {
   365  		return nil, err
   366  	}
   367  
   368  	response := Response{
   369  		StatusCode: res.StatusCode,
   370  		Body:       res.Body,
   371  		Header:     res.Header,
   372  	}
   373  
   374  	return &response, nil
   375  }
   376  
   377  // WithContext sets the request context.
   378  //
   379  func (f Search) WithContext(v context.Context) func(*SearchRequest) {
   380  	return func(r *SearchRequest) {
   381  		r.ctx = v
   382  	}
   383  }
   384  
   385  // WithBody - The search definition using the Query DSL.
   386  //
   387  func (f Search) WithBody(v io.Reader) func(*SearchRequest) {
   388  	return func(r *SearchRequest) {
   389  		r.Body = v
   390  	}
   391  }
   392  
   393  // WithIndex - a list of index names to search; use _all to perform the operation on all indices.
   394  //
   395  func (f Search) WithIndex(v ...string) func(*SearchRequest) {
   396  	return func(r *SearchRequest) {
   397  		r.Index = v
   398  	}
   399  }
   400  
   401  // 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).
   402  //
   403  func (f Search) WithAllowNoIndices(v bool) func(*SearchRequest) {
   404  	return func(r *SearchRequest) {
   405  		r.AllowNoIndices = &v
   406  	}
   407  }
   408  
   409  // WithAllowPartialSearchResults - indicate if an error should be returned if there is a partial search failure or timeout.
   410  //
   411  func (f Search) WithAllowPartialSearchResults(v bool) func(*SearchRequest) {
   412  	return func(r *SearchRequest) {
   413  		r.AllowPartialSearchResults = &v
   414  	}
   415  }
   416  
   417  // WithAnalyzer - the analyzer to use for the query string.
   418  //
   419  func (f Search) WithAnalyzer(v string) func(*SearchRequest) {
   420  	return func(r *SearchRequest) {
   421  		r.Analyzer = v
   422  	}
   423  }
   424  
   425  // WithAnalyzeWildcard - specify whether wildcard and prefix queries should be analyzed (default: false).
   426  //
   427  func (f Search) WithAnalyzeWildcard(v bool) func(*SearchRequest) {
   428  	return func(r *SearchRequest) {
   429  		r.AnalyzeWildcard = &v
   430  	}
   431  }
   432  
   433  // WithBatchedReduceSize - the number of shard results that should be reduced at once on the coordinating node. this value should be used as a protection mechanism to reduce the memory overhead per search request if the potential number of shards in the request can be large..
   434  //
   435  func (f Search) WithBatchedReduceSize(v int) func(*SearchRequest) {
   436  	return func(r *SearchRequest) {
   437  		r.BatchedReduceSize = &v
   438  	}
   439  }
   440  
   441  // WithCcsMinimizeRoundtrips - indicates whether network round-trips should be minimized as part of cross-cluster search requests execution.
   442  //
   443  func (f Search) WithCcsMinimizeRoundtrips(v bool) func(*SearchRequest) {
   444  	return func(r *SearchRequest) {
   445  		r.CcsMinimizeRoundtrips = &v
   446  	}
   447  }
   448  
   449  // WithDefaultOperator - the default operator for query string query (and or or).
   450  //
   451  func (f Search) WithDefaultOperator(v string) func(*SearchRequest) {
   452  	return func(r *SearchRequest) {
   453  		r.DefaultOperator = v
   454  	}
   455  }
   456  
   457  // WithDf - the field to use as default where no field prefix is given in the query string.
   458  //
   459  func (f Search) WithDf(v string) func(*SearchRequest) {
   460  	return func(r *SearchRequest) {
   461  		r.Df = v
   462  	}
   463  }
   464  
   465  // WithDocvalueFields - a list of fields to return as the docvalue representation of a field for each hit.
   466  //
   467  func (f Search) WithDocvalueFields(v ...string) func(*SearchRequest) {
   468  	return func(r *SearchRequest) {
   469  		r.DocvalueFields = v
   470  	}
   471  }
   472  
   473  // WithExpandWildcards - whether to expand wildcard expression to concrete indices that are open, closed or both..
   474  //
   475  func (f Search) WithExpandWildcards(v string) func(*SearchRequest) {
   476  	return func(r *SearchRequest) {
   477  		r.ExpandWildcards = v
   478  	}
   479  }
   480  
   481  // WithExplain - specify whether to return detailed information about score computation as part of a hit.
   482  //
   483  func (f Search) WithExplain(v bool) func(*SearchRequest) {
   484  	return func(r *SearchRequest) {
   485  		r.Explain = &v
   486  	}
   487  }
   488  
   489  // WithFrom - starting offset (default: 0).
   490  //
   491  func (f Search) WithFrom(v int) func(*SearchRequest) {
   492  	return func(r *SearchRequest) {
   493  		r.From = &v
   494  	}
   495  }
   496  
   497  // WithIgnoreThrottled - whether specified concrete, expanded or aliased indices should be ignored when throttled.
   498  //
   499  func (f Search) WithIgnoreThrottled(v bool) func(*SearchRequest) {
   500  	return func(r *SearchRequest) {
   501  		r.IgnoreThrottled = &v
   502  	}
   503  }
   504  
   505  // WithIgnoreUnavailable - whether specified concrete indices should be ignored when unavailable (missing or closed).
   506  //
   507  func (f Search) WithIgnoreUnavailable(v bool) func(*SearchRequest) {
   508  	return func(r *SearchRequest) {
   509  		r.IgnoreUnavailable = &v
   510  	}
   511  }
   512  
   513  // WithLenient - specify whether format-based query failures (such as providing text to a numeric field) should be ignored.
   514  //
   515  func (f Search) WithLenient(v bool) func(*SearchRequest) {
   516  	return func(r *SearchRequest) {
   517  		r.Lenient = &v
   518  	}
   519  }
   520  
   521  // WithMaxConcurrentShardRequests - the number of concurrent shard requests per node this search executes concurrently. 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.
   522  //
   523  func (f Search) WithMaxConcurrentShardRequests(v int) func(*SearchRequest) {
   524  	return func(r *SearchRequest) {
   525  		r.MaxConcurrentShardRequests = &v
   526  	}
   527  }
   528  
   529  // WithMinCompatibleShardNode - the minimum compatible version that all shards involved in search should have for this request to be successful.
   530  //
   531  func (f Search) WithMinCompatibleShardNode(v string) func(*SearchRequest) {
   532  	return func(r *SearchRequest) {
   533  		r.MinCompatibleShardNode = v
   534  	}
   535  }
   536  
   537  // WithPreference - specify the node or shard the operation should be performed on (default: random).
   538  //
   539  func (f Search) WithPreference(v string) func(*SearchRequest) {
   540  	return func(r *SearchRequest) {
   541  		r.Preference = v
   542  	}
   543  }
   544  
   545  // 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..
   546  //
   547  func (f Search) WithPreFilterShardSize(v int) func(*SearchRequest) {
   548  	return func(r *SearchRequest) {
   549  		r.PreFilterShardSize = &v
   550  	}
   551  }
   552  
   553  // WithQuery - query in the lucene query string syntax.
   554  //
   555  func (f Search) WithQuery(v string) func(*SearchRequest) {
   556  	return func(r *SearchRequest) {
   557  		r.Query = v
   558  	}
   559  }
   560  
   561  // WithRequestCache - specify if request cache should be used for this request or not, defaults to index level setting.
   562  //
   563  func (f Search) WithRequestCache(v bool) func(*SearchRequest) {
   564  	return func(r *SearchRequest) {
   565  		r.RequestCache = &v
   566  	}
   567  }
   568  
   569  // WithRestTotalHitsAsInt - indicates whether hits.total should be rendered as an integer or an object in the rest search response.
   570  //
   571  func (f Search) WithRestTotalHitsAsInt(v bool) func(*SearchRequest) {
   572  	return func(r *SearchRequest) {
   573  		r.RestTotalHitsAsInt = &v
   574  	}
   575  }
   576  
   577  // WithRouting - a list of specific routing values.
   578  //
   579  func (f Search) WithRouting(v ...string) func(*SearchRequest) {
   580  	return func(r *SearchRequest) {
   581  		r.Routing = v
   582  	}
   583  }
   584  
   585  // WithScroll - specify how long a consistent view of the index should be maintained for scrolled search.
   586  //
   587  func (f Search) WithScroll(v time.Duration) func(*SearchRequest) {
   588  	return func(r *SearchRequest) {
   589  		r.Scroll = v
   590  	}
   591  }
   592  
   593  // WithSearchType - search operation type.
   594  //
   595  func (f Search) WithSearchType(v string) func(*SearchRequest) {
   596  	return func(r *SearchRequest) {
   597  		r.SearchType = v
   598  	}
   599  }
   600  
   601  // WithSeqNoPrimaryTerm - specify whether to return sequence number and primary term of the last modification of each hit.
   602  //
   603  func (f Search) WithSeqNoPrimaryTerm(v bool) func(*SearchRequest) {
   604  	return func(r *SearchRequest) {
   605  		r.SeqNoPrimaryTerm = &v
   606  	}
   607  }
   608  
   609  // WithSize - number of hits to return (default: 10).
   610  //
   611  func (f Search) WithSize(v int) func(*SearchRequest) {
   612  	return func(r *SearchRequest) {
   613  		r.Size = &v
   614  	}
   615  }
   616  
   617  // WithSort - a list of <field>:<direction> pairs.
   618  //
   619  func (f Search) WithSort(v ...string) func(*SearchRequest) {
   620  	return func(r *SearchRequest) {
   621  		r.Sort = v
   622  	}
   623  }
   624  
   625  // WithSource - true or false to return the _source field or not, or a list of fields to return.
   626  //
   627  func (f Search) WithSource(v interface{}) func(*SearchRequest) {
   628  	return func(r *SearchRequest) {
   629  		r.Source = v
   630  	}
   631  }
   632  
   633  // WithSourceExcludes - a list of fields to exclude from the returned _source field.
   634  //
   635  func (f Search) WithSourceExcludes(v ...string) func(*SearchRequest) {
   636  	return func(r *SearchRequest) {
   637  		r.SourceExcludes = v
   638  	}
   639  }
   640  
   641  // WithSourceIncludes - a list of fields to extract and return from the _source field.
   642  //
   643  func (f Search) WithSourceIncludes(v ...string) func(*SearchRequest) {
   644  	return func(r *SearchRequest) {
   645  		r.SourceIncludes = v
   646  	}
   647  }
   648  
   649  // WithStats - specific 'tag' of the request for logging and statistical purposes.
   650  //
   651  func (f Search) WithStats(v ...string) func(*SearchRequest) {
   652  	return func(r *SearchRequest) {
   653  		r.Stats = v
   654  	}
   655  }
   656  
   657  // WithStoredFields - a list of stored fields to return as part of a hit.
   658  //
   659  func (f Search) WithStoredFields(v ...string) func(*SearchRequest) {
   660  	return func(r *SearchRequest) {
   661  		r.StoredFields = v
   662  	}
   663  }
   664  
   665  // WithSuggestField - specify which field to use for suggestions.
   666  //
   667  func (f Search) WithSuggestField(v string) func(*SearchRequest) {
   668  	return func(r *SearchRequest) {
   669  		r.SuggestField = v
   670  	}
   671  }
   672  
   673  // WithSuggestMode - specify suggest mode.
   674  //
   675  func (f Search) WithSuggestMode(v string) func(*SearchRequest) {
   676  	return func(r *SearchRequest) {
   677  		r.SuggestMode = v
   678  	}
   679  }
   680  
   681  // WithSuggestSize - how many suggestions to return in response.
   682  //
   683  func (f Search) WithSuggestSize(v int) func(*SearchRequest) {
   684  	return func(r *SearchRequest) {
   685  		r.SuggestSize = &v
   686  	}
   687  }
   688  
   689  // WithSuggestText - the source text for which the suggestions should be returned.
   690  //
   691  func (f Search) WithSuggestText(v string) func(*SearchRequest) {
   692  	return func(r *SearchRequest) {
   693  		r.SuggestText = v
   694  	}
   695  }
   696  
   697  // WithTerminateAfter - the maximum number of documents to collect for each shard, upon reaching which the query execution will terminate early..
   698  //
   699  func (f Search) WithTerminateAfter(v int) func(*SearchRequest) {
   700  	return func(r *SearchRequest) {
   701  		r.TerminateAfter = &v
   702  	}
   703  }
   704  
   705  // WithTimeout - explicit operation timeout.
   706  //
   707  func (f Search) WithTimeout(v time.Duration) func(*SearchRequest) {
   708  	return func(r *SearchRequest) {
   709  		r.Timeout = v
   710  	}
   711  }
   712  
   713  // WithTrackScores - whether to calculate and return scores even if they are not used for sorting.
   714  //
   715  func (f Search) WithTrackScores(v bool) func(*SearchRequest) {
   716  	return func(r *SearchRequest) {
   717  		r.TrackScores = &v
   718  	}
   719  }
   720  
   721  // WithTrackTotalHits - indicate if the number of documents that match the query should be tracked.
   722  //
   723  func (f Search) WithTrackTotalHits(v interface{}) func(*SearchRequest) {
   724  	return func(r *SearchRequest) {
   725  		r.TrackTotalHits = v
   726  	}
   727  }
   728  
   729  // WithTypedKeys - specify whether aggregation and suggester names should be prefixed by their respective types in the response.
   730  //
   731  func (f Search) WithTypedKeys(v bool) func(*SearchRequest) {
   732  	return func(r *SearchRequest) {
   733  		r.TypedKeys = &v
   734  	}
   735  }
   736  
   737  // WithVersion - specify whether to return document version as part of a hit.
   738  //
   739  func (f Search) WithVersion(v bool) func(*SearchRequest) {
   740  	return func(r *SearchRequest) {
   741  		r.Version = &v
   742  	}
   743  }
   744  
   745  // WithPretty makes the response body pretty-printed.
   746  //
   747  func (f Search) WithPretty() func(*SearchRequest) {
   748  	return func(r *SearchRequest) {
   749  		r.Pretty = true
   750  	}
   751  }
   752  
   753  // WithHuman makes statistical values human-readable.
   754  //
   755  func (f Search) WithHuman() func(*SearchRequest) {
   756  	return func(r *SearchRequest) {
   757  		r.Human = true
   758  	}
   759  }
   760  
   761  // WithErrorTrace includes the stack trace for errors in the response body.
   762  //
   763  func (f Search) WithErrorTrace() func(*SearchRequest) {
   764  	return func(r *SearchRequest) {
   765  		r.ErrorTrace = true
   766  	}
   767  }
   768  
   769  // WithFilterPath filters the properties of the response body.
   770  //
   771  func (f Search) WithFilterPath(v ...string) func(*SearchRequest) {
   772  	return func(r *SearchRequest) {
   773  		r.FilterPath = v
   774  	}
   775  }
   776  
   777  // WithHeader adds the headers to the HTTP request.
   778  //
   779  func (f Search) WithHeader(h map[string]string) func(*SearchRequest) {
   780  	return func(r *SearchRequest) {
   781  		if r.Header == nil {
   782  			r.Header = make(http.Header)
   783  		}
   784  		for k, v := range h {
   785  			r.Header.Add(k, v)
   786  		}
   787  	}
   788  }
   789  
   790  // WithOpaqueID adds the X-Opaque-Id header to the HTTP request.
   791  //
   792  func (f Search) WithOpaqueID(s string) func(*SearchRequest) {
   793  	return func(r *SearchRequest) {
   794  		if r.Header == nil {
   795  			r.Header = make(http.Header)
   796  		}
   797  		r.Header.Set("X-Opaque-Id", s)
   798  	}
   799  }