github.com/opensearch-project/opensearch-go/v2@v2.3.0/opensearchapi/api.update_by_query.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 newUpdateByQueryFunc(t Transport) UpdateByQuery { 40 return func(index []string, o ...func(*UpdateByQueryRequest)) (*Response, error) { 41 var r = UpdateByQueryRequest{Index: index} 42 for _, f := range o { 43 f(&r) 44 } 45 return r.Do(r.ctx, t) 46 } 47 } 48 49 // ----- API Definition ------------------------------------------------------- 50 51 // UpdateByQuery performs an update on every document in the index without changing the source, 52 // for example to pick up a mapping change. 53 // 54 // 55 type UpdateByQuery func(index []string, o ...func(*UpdateByQueryRequest)) (*Response, error) 56 57 // UpdateByQueryRequest configures the Update By Query API request. 58 // 59 type UpdateByQueryRequest struct { 60 Index []string 61 62 Body io.Reader 63 64 AllowNoIndices *bool 65 Analyzer string 66 AnalyzeWildcard *bool 67 Conflicts string 68 DefaultOperator string 69 Df string 70 ExpandWildcards string 71 From *int 72 IgnoreUnavailable *bool 73 Lenient *bool 74 MaxDocs *int 75 Pipeline string 76 Preference string 77 Query string 78 Refresh *bool 79 RequestCache *bool 80 RequestsPerSecond *int 81 Routing []string 82 Scroll time.Duration 83 ScrollSize *int 84 SearchTimeout time.Duration 85 SearchType string 86 Size *int 87 Slices interface{} 88 Sort []string 89 Source interface{} 90 SourceExcludes []string 91 SourceIncludes []string 92 Stats []string 93 TerminateAfter *int 94 Timeout time.Duration 95 Version *bool 96 VersionType *bool 97 WaitForActiveShards string 98 WaitForCompletion *bool 99 100 Pretty bool 101 Human bool 102 ErrorTrace bool 103 FilterPath []string 104 105 Header http.Header 106 107 ctx context.Context 108 } 109 110 // Do executes the request and returns response or error. 111 // 112 func (r UpdateByQueryRequest) Do(ctx context.Context, transport Transport) (*Response, error) { 113 var ( 114 method string 115 path strings.Builder 116 params map[string]string 117 ) 118 119 method = "POST" 120 121 path.Grow(1 + len(strings.Join(r.Index, ",")) + 1 + len("_update_by_query")) 122 path.WriteString("/") 123 path.WriteString(strings.Join(r.Index, ",")) 124 path.WriteString("/") 125 path.WriteString("_update_by_query") 126 127 params = make(map[string]string) 128 129 if r.AllowNoIndices != nil { 130 params["allow_no_indices"] = strconv.FormatBool(*r.AllowNoIndices) 131 } 132 133 if r.Analyzer != "" { 134 params["analyzer"] = r.Analyzer 135 } 136 137 if r.AnalyzeWildcard != nil { 138 params["analyze_wildcard"] = strconv.FormatBool(*r.AnalyzeWildcard) 139 } 140 141 if r.Conflicts != "" { 142 params["conflicts"] = r.Conflicts 143 } 144 145 if r.DefaultOperator != "" { 146 params["default_operator"] = r.DefaultOperator 147 } 148 149 if r.Df != "" { 150 params["df"] = r.Df 151 } 152 153 if r.ExpandWildcards != "" { 154 params["expand_wildcards"] = r.ExpandWildcards 155 } 156 157 if r.From != nil { 158 params["from"] = strconv.FormatInt(int64(*r.From), 10) 159 } 160 161 if r.IgnoreUnavailable != nil { 162 params["ignore_unavailable"] = strconv.FormatBool(*r.IgnoreUnavailable) 163 } 164 165 if r.Lenient != nil { 166 params["lenient"] = strconv.FormatBool(*r.Lenient) 167 } 168 169 if r.MaxDocs != nil { 170 params["max_docs"] = strconv.FormatInt(int64(*r.MaxDocs), 10) 171 } 172 173 if r.Pipeline != "" { 174 params["pipeline"] = r.Pipeline 175 } 176 177 if r.Preference != "" { 178 params["preference"] = r.Preference 179 } 180 181 if r.Query != "" { 182 params["q"] = r.Query 183 } 184 185 if r.Refresh != nil { 186 params["refresh"] = strconv.FormatBool(*r.Refresh) 187 } 188 189 if r.RequestCache != nil { 190 params["request_cache"] = strconv.FormatBool(*r.RequestCache) 191 } 192 193 if r.RequestsPerSecond != nil { 194 params["requests_per_second"] = strconv.FormatInt(int64(*r.RequestsPerSecond), 10) 195 } 196 197 if len(r.Routing) > 0 { 198 params["routing"] = strings.Join(r.Routing, ",") 199 } 200 201 if r.Scroll != 0 { 202 params["scroll"] = formatDuration(r.Scroll) 203 } 204 205 if r.ScrollSize != nil { 206 params["scroll_size"] = strconv.FormatInt(int64(*r.ScrollSize), 10) 207 } 208 209 if r.SearchTimeout != 0 { 210 params["search_timeout"] = formatDuration(r.SearchTimeout) 211 } 212 213 if r.SearchType != "" { 214 params["search_type"] = r.SearchType 215 } 216 217 if r.Size != nil { 218 params["size"] = strconv.FormatInt(int64(*r.Size), 10) 219 } 220 221 if r.Slices != nil { 222 params["slices"] = fmt.Sprintf("%v", r.Slices) 223 } 224 225 if len(r.Sort) > 0 { 226 params["sort"] = strings.Join(r.Sort, ",") 227 } 228 229 if source, ok := r.Source.(bool); ok { 230 params["_source"] = strconv.FormatBool(source) 231 } else if source, ok := r.Source.(string); ok && source != "" { 232 params["_source"] = source 233 } else if sources, ok := r.Source.([]string); ok && len(sources) > 0 { 234 params["_source"] = strings.Join(sources, ",") 235 } 236 237 if len(r.SourceExcludes) > 0 { 238 params["_source_excludes"] = strings.Join(r.SourceExcludes, ",") 239 } 240 241 if len(r.SourceIncludes) > 0 { 242 params["_source_includes"] = strings.Join(r.SourceIncludes, ",") 243 } 244 245 if len(r.Stats) > 0 { 246 params["stats"] = strings.Join(r.Stats, ",") 247 } 248 249 if r.TerminateAfter != nil { 250 params["terminate_after"] = strconv.FormatInt(int64(*r.TerminateAfter), 10) 251 } 252 253 if r.Timeout != 0 { 254 params["timeout"] = formatDuration(r.Timeout) 255 } 256 257 if r.Version != nil { 258 params["version"] = strconv.FormatBool(*r.Version) 259 } 260 261 if r.VersionType != nil { 262 params["version_type"] = strconv.FormatBool(*r.VersionType) 263 } 264 265 if r.WaitForActiveShards != "" { 266 params["wait_for_active_shards"] = r.WaitForActiveShards 267 } 268 269 if r.WaitForCompletion != nil { 270 params["wait_for_completion"] = strconv.FormatBool(*r.WaitForCompletion) 271 } 272 273 if r.Pretty { 274 params["pretty"] = "true" 275 } 276 277 if r.Human { 278 params["human"] = "true" 279 } 280 281 if r.ErrorTrace { 282 params["error_trace"] = "true" 283 } 284 285 if len(r.FilterPath) > 0 { 286 params["filter_path"] = strings.Join(r.FilterPath, ",") 287 } 288 289 req, err := newRequest(method, path.String(), r.Body) 290 if err != nil { 291 return nil, err 292 } 293 294 if len(params) > 0 { 295 q := req.URL.Query() 296 for k, v := range params { 297 q.Set(k, v) 298 } 299 req.URL.RawQuery = q.Encode() 300 } 301 302 if r.Body != nil { 303 req.Header[headerContentType] = headerContentTypeJSON 304 } 305 306 if len(r.Header) > 0 { 307 if len(req.Header) == 0 { 308 req.Header = r.Header 309 } else { 310 for k, vv := range r.Header { 311 for _, v := range vv { 312 req.Header.Add(k, v) 313 } 314 } 315 } 316 } 317 318 if ctx != nil { 319 req = req.WithContext(ctx) 320 } 321 322 res, err := transport.Perform(req) 323 if err != nil { 324 return nil, err 325 } 326 327 response := Response{ 328 StatusCode: res.StatusCode, 329 Body: res.Body, 330 Header: res.Header, 331 } 332 333 return &response, nil 334 } 335 336 // WithContext sets the request context. 337 // 338 func (f UpdateByQuery) WithContext(v context.Context) func(*UpdateByQueryRequest) { 339 return func(r *UpdateByQueryRequest) { 340 r.ctx = v 341 } 342 } 343 344 // WithBody - The search definition using the Query DSL. 345 // 346 func (f UpdateByQuery) WithBody(v io.Reader) func(*UpdateByQueryRequest) { 347 return func(r *UpdateByQueryRequest) { 348 r.Body = v 349 } 350 } 351 352 // 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). 353 // 354 func (f UpdateByQuery) WithAllowNoIndices(v bool) func(*UpdateByQueryRequest) { 355 return func(r *UpdateByQueryRequest) { 356 r.AllowNoIndices = &v 357 } 358 } 359 360 // WithAnalyzer - the analyzer to use for the query string. 361 // 362 func (f UpdateByQuery) WithAnalyzer(v string) func(*UpdateByQueryRequest) { 363 return func(r *UpdateByQueryRequest) { 364 r.Analyzer = v 365 } 366 } 367 368 // WithAnalyzeWildcard - specify whether wildcard and prefix queries should be analyzed (default: false). 369 // 370 func (f UpdateByQuery) WithAnalyzeWildcard(v bool) func(*UpdateByQueryRequest) { 371 return func(r *UpdateByQueryRequest) { 372 r.AnalyzeWildcard = &v 373 } 374 } 375 376 // WithConflicts - what to do when the update by query hits version conflicts?. 377 // 378 func (f UpdateByQuery) WithConflicts(v string) func(*UpdateByQueryRequest) { 379 return func(r *UpdateByQueryRequest) { 380 r.Conflicts = v 381 } 382 } 383 384 // WithDefaultOperator - the default operator for query string query (and or or). 385 // 386 func (f UpdateByQuery) WithDefaultOperator(v string) func(*UpdateByQueryRequest) { 387 return func(r *UpdateByQueryRequest) { 388 r.DefaultOperator = v 389 } 390 } 391 392 // WithDf - the field to use as default where no field prefix is given in the query string. 393 // 394 func (f UpdateByQuery) WithDf(v string) func(*UpdateByQueryRequest) { 395 return func(r *UpdateByQueryRequest) { 396 r.Df = v 397 } 398 } 399 400 // WithExpandWildcards - whether to expand wildcard expression to concrete indices that are open, closed or both.. 401 // 402 func (f UpdateByQuery) WithExpandWildcards(v string) func(*UpdateByQueryRequest) { 403 return func(r *UpdateByQueryRequest) { 404 r.ExpandWildcards = v 405 } 406 } 407 408 // WithFrom - starting offset (default: 0). 409 // 410 func (f UpdateByQuery) WithFrom(v int) func(*UpdateByQueryRequest) { 411 return func(r *UpdateByQueryRequest) { 412 r.From = &v 413 } 414 } 415 416 // WithIgnoreUnavailable - whether specified concrete indices should be ignored when unavailable (missing or closed). 417 // 418 func (f UpdateByQuery) WithIgnoreUnavailable(v bool) func(*UpdateByQueryRequest) { 419 return func(r *UpdateByQueryRequest) { 420 r.IgnoreUnavailable = &v 421 } 422 } 423 424 // WithLenient - specify whether format-based query failures (such as providing text to a numeric field) should be ignored. 425 // 426 func (f UpdateByQuery) WithLenient(v bool) func(*UpdateByQueryRequest) { 427 return func(r *UpdateByQueryRequest) { 428 r.Lenient = &v 429 } 430 } 431 432 // WithMaxDocs - maximum number of documents to process (default: all documents). 433 // 434 func (f UpdateByQuery) WithMaxDocs(v int) func(*UpdateByQueryRequest) { 435 return func(r *UpdateByQueryRequest) { 436 r.MaxDocs = &v 437 } 438 } 439 440 // WithPipeline - ingest pipeline to set on index requests made by this action. (default: none). 441 // 442 func (f UpdateByQuery) WithPipeline(v string) func(*UpdateByQueryRequest) { 443 return func(r *UpdateByQueryRequest) { 444 r.Pipeline = v 445 } 446 } 447 448 // WithPreference - specify the node or shard the operation should be performed on (default: random). 449 // 450 func (f UpdateByQuery) WithPreference(v string) func(*UpdateByQueryRequest) { 451 return func(r *UpdateByQueryRequest) { 452 r.Preference = v 453 } 454 } 455 456 // WithQuery - query in the lucene query string syntax. 457 // 458 func (f UpdateByQuery) WithQuery(v string) func(*UpdateByQueryRequest) { 459 return func(r *UpdateByQueryRequest) { 460 r.Query = v 461 } 462 } 463 464 // WithRefresh - should the affected indexes be refreshed?. 465 // 466 func (f UpdateByQuery) WithRefresh(v bool) func(*UpdateByQueryRequest) { 467 return func(r *UpdateByQueryRequest) { 468 r.Refresh = &v 469 } 470 } 471 472 // WithRequestCache - specify if request cache should be used for this request or not, defaults to index level setting. 473 // 474 func (f UpdateByQuery) WithRequestCache(v bool) func(*UpdateByQueryRequest) { 475 return func(r *UpdateByQueryRequest) { 476 r.RequestCache = &v 477 } 478 } 479 480 // WithRequestsPerSecond - the throttle to set on this request in sub-requests per second. -1 means no throttle.. 481 // 482 func (f UpdateByQuery) WithRequestsPerSecond(v int) func(*UpdateByQueryRequest) { 483 return func(r *UpdateByQueryRequest) { 484 r.RequestsPerSecond = &v 485 } 486 } 487 488 // WithRouting - a list of specific routing values. 489 // 490 func (f UpdateByQuery) WithRouting(v ...string) func(*UpdateByQueryRequest) { 491 return func(r *UpdateByQueryRequest) { 492 r.Routing = v 493 } 494 } 495 496 // WithScroll - specify how long a consistent view of the index should be maintained for scrolled search. 497 // 498 func (f UpdateByQuery) WithScroll(v time.Duration) func(*UpdateByQueryRequest) { 499 return func(r *UpdateByQueryRequest) { 500 r.Scroll = v 501 } 502 } 503 504 // WithScrollSize - size on the scroll request powering the update by query. 505 // 506 func (f UpdateByQuery) WithScrollSize(v int) func(*UpdateByQueryRequest) { 507 return func(r *UpdateByQueryRequest) { 508 r.ScrollSize = &v 509 } 510 } 511 512 // WithSearchTimeout - explicit timeout for each search request. defaults to no timeout.. 513 // 514 func (f UpdateByQuery) WithSearchTimeout(v time.Duration) func(*UpdateByQueryRequest) { 515 return func(r *UpdateByQueryRequest) { 516 r.SearchTimeout = v 517 } 518 } 519 520 // WithSearchType - search operation type. 521 // 522 func (f UpdateByQuery) WithSearchType(v string) func(*UpdateByQueryRequest) { 523 return func(r *UpdateByQueryRequest) { 524 r.SearchType = v 525 } 526 } 527 528 // WithSize - deprecated, please use `max_docs` instead. 529 // 530 func (f UpdateByQuery) WithSize(v int) func(*UpdateByQueryRequest) { 531 return func(r *UpdateByQueryRequest) { 532 r.Size = &v 533 } 534 } 535 536 // WithSlices - the number of slices this task should be divided into. defaults to 1, meaning the task isn't sliced into subtasks. can be set to `auto`.. 537 // 538 func (f UpdateByQuery) WithSlices(v interface{}) func(*UpdateByQueryRequest) { 539 return func(r *UpdateByQueryRequest) { 540 r.Slices = v 541 } 542 } 543 544 // WithSort - a list of <field>:<direction> pairs. 545 // 546 func (f UpdateByQuery) WithSort(v ...string) func(*UpdateByQueryRequest) { 547 return func(r *UpdateByQueryRequest) { 548 r.Sort = v 549 } 550 } 551 552 // WithSource - true or false to return the _source field or not, or a list of fields to return. 553 // 554 func (f UpdateByQuery) WithSource(v interface{}) func(*UpdateByQueryRequest) { 555 return func(r *UpdateByQueryRequest) { 556 r.Source = v 557 } 558 } 559 560 // WithSourceExcludes - a list of fields to exclude from the returned _source field. 561 // 562 func (f UpdateByQuery) WithSourceExcludes(v ...string) func(*UpdateByQueryRequest) { 563 return func(r *UpdateByQueryRequest) { 564 r.SourceExcludes = v 565 } 566 } 567 568 // WithSourceIncludes - a list of fields to extract and return from the _source field. 569 // 570 func (f UpdateByQuery) WithSourceIncludes(v ...string) func(*UpdateByQueryRequest) { 571 return func(r *UpdateByQueryRequest) { 572 r.SourceIncludes = v 573 } 574 } 575 576 // WithStats - specific 'tag' of the request for logging and statistical purposes. 577 // 578 func (f UpdateByQuery) WithStats(v ...string) func(*UpdateByQueryRequest) { 579 return func(r *UpdateByQueryRequest) { 580 r.Stats = v 581 } 582 } 583 584 // WithTerminateAfter - the maximum number of documents to collect for each shard, upon reaching which the query execution will terminate early.. 585 // 586 func (f UpdateByQuery) WithTerminateAfter(v int) func(*UpdateByQueryRequest) { 587 return func(r *UpdateByQueryRequest) { 588 r.TerminateAfter = &v 589 } 590 } 591 592 // WithTimeout - time each individual bulk request should wait for shards that are unavailable.. 593 // 594 func (f UpdateByQuery) WithTimeout(v time.Duration) func(*UpdateByQueryRequest) { 595 return func(r *UpdateByQueryRequest) { 596 r.Timeout = v 597 } 598 } 599 600 // WithVersion - specify whether to return document version as part of a hit. 601 // 602 func (f UpdateByQuery) WithVersion(v bool) func(*UpdateByQueryRequest) { 603 return func(r *UpdateByQueryRequest) { 604 r.Version = &v 605 } 606 } 607 608 // WithVersionType - should the document increment the version number (internal) on hit or not (reindex). 609 // 610 func (f UpdateByQuery) WithVersionType(v bool) func(*UpdateByQueryRequest) { 611 return func(r *UpdateByQueryRequest) { 612 r.VersionType = &v 613 } 614 } 615 616 // WithWaitForActiveShards - sets the number of shard copies that must be active before proceeding with the update by query operation. defaults to 1, meaning the primary shard only. set to `all` for all shard copies, otherwise set to any non-negative value less than or equal to the total number of copies for the shard (number of replicas + 1). 617 // 618 func (f UpdateByQuery) WithWaitForActiveShards(v string) func(*UpdateByQueryRequest) { 619 return func(r *UpdateByQueryRequest) { 620 r.WaitForActiveShards = v 621 } 622 } 623 624 // WithWaitForCompletion - should the request should block until the update by query operation is complete.. 625 // 626 func (f UpdateByQuery) WithWaitForCompletion(v bool) func(*UpdateByQueryRequest) { 627 return func(r *UpdateByQueryRequest) { 628 r.WaitForCompletion = &v 629 } 630 } 631 632 // WithPretty makes the response body pretty-printed. 633 // 634 func (f UpdateByQuery) WithPretty() func(*UpdateByQueryRequest) { 635 return func(r *UpdateByQueryRequest) { 636 r.Pretty = true 637 } 638 } 639 640 // WithHuman makes statistical values human-readable. 641 // 642 func (f UpdateByQuery) WithHuman() func(*UpdateByQueryRequest) { 643 return func(r *UpdateByQueryRequest) { 644 r.Human = true 645 } 646 } 647 648 // WithErrorTrace includes the stack trace for errors in the response body. 649 // 650 func (f UpdateByQuery) WithErrorTrace() func(*UpdateByQueryRequest) { 651 return func(r *UpdateByQueryRequest) { 652 r.ErrorTrace = true 653 } 654 } 655 656 // WithFilterPath filters the properties of the response body. 657 // 658 func (f UpdateByQuery) WithFilterPath(v ...string) func(*UpdateByQueryRequest) { 659 return func(r *UpdateByQueryRequest) { 660 r.FilterPath = v 661 } 662 } 663 664 // WithHeader adds the headers to the HTTP request. 665 // 666 func (f UpdateByQuery) WithHeader(h map[string]string) func(*UpdateByQueryRequest) { 667 return func(r *UpdateByQueryRequest) { 668 if r.Header == nil { 669 r.Header = make(http.Header) 670 } 671 for k, v := range h { 672 r.Header.Add(k, v) 673 } 674 } 675 } 676 677 // WithOpaqueID adds the X-Opaque-Id header to the HTTP request. 678 // 679 func (f UpdateByQuery) WithOpaqueID(s string) func(*UpdateByQueryRequest) { 680 return func(r *UpdateByQueryRequest) { 681 if r.Header == nil { 682 r.Header = make(http.Header) 683 } 684 r.Header.Set("X-Opaque-Id", s) 685 } 686 }