github.com/opensearch-project/opensearch-go/v2@v2.3.0/opensearchutil/bulk_indexer_example_test.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 // +build !integration 28 29 package opensearchutil_test 30 31 import ( 32 "context" 33 "fmt" 34 "log" 35 "strings" 36 "time" 37 38 "github.com/opensearch-project/opensearch-go/v2" 39 "github.com/opensearch-project/opensearch-go/v2/opensearchutil" 40 ) 41 42 func ExampleNewBulkIndexer() { 43 log.SetFlags(0) 44 45 // Create the OpenSearch client 46 // 47 client, err := opensearch.NewClient(opensearch.Config{ 48 // Retry on 429 TooManyRequests statuses 49 // 50 RetryOnStatus: []int{502, 503, 504, 429}, 51 52 // A simple incremental backoff function 53 // 54 RetryBackoff: func(i int) time.Duration { return time.Duration(i) * 100 * time.Millisecond }, 55 56 // Retry up to 5 attempts 57 // 58 MaxRetries: 5, 59 }) 60 if err != nil { 61 log.Fatalf("Error creating the client: %s", err) 62 } 63 64 // Create the indexer 65 // 66 indexer, err := opensearchutil.NewBulkIndexer(opensearchutil.BulkIndexerConfig{ 67 Client: client, // The OpenSearch client 68 Index: "test", // The default index name 69 NumWorkers: 4, // The number of worker goroutines (default: number of CPUs) 70 FlushBytes: 5e+6, // The flush threshold in bytes (default: 5M) 71 }) 72 if err != nil { 73 log.Fatalf("Error creating the indexer: %s", err) 74 } 75 76 // Add an item to the indexer 77 // 78 err = indexer.Add( 79 context.Background(), 80 opensearchutil.BulkIndexerItem{ 81 // Action field configures the operation to perform (index, create, delete, update) 82 Action: "index", 83 84 // DocumentID is the optional document ID 85 DocumentID: "1", 86 87 // Body is an `io.Reader` with the payload 88 Body: strings.NewReader(`{"title":"Test"}`), 89 90 // OnSuccess is the optional callback for each successful operation 91 OnSuccess: func( 92 ctx context.Context, 93 item opensearchutil.BulkIndexerItem, 94 res opensearchutil.BulkIndexerResponseItem, 95 ) { 96 fmt.Printf("[%d] %s test/%s", res.Status, res.Result, item.DocumentID) 97 }, 98 99 // OnFailure is the optional callback for each failed operation 100 OnFailure: func( 101 ctx context.Context, 102 item opensearchutil.BulkIndexerItem, 103 res opensearchutil.BulkIndexerResponseItem, err error, 104 ) { 105 if err != nil { 106 log.Printf("ERROR: %s", err) 107 } else { 108 log.Printf("ERROR: %s: %s", res.Error.Type, res.Error.Reason) 109 } 110 }, 111 }, 112 ) 113 if err != nil { 114 log.Fatalf("Unexpected error: %s", err) 115 } 116 117 // Close the indexer channel and flush remaining items 118 // 119 if err := indexer.Close(context.Background()); err != nil { 120 log.Fatalf("Unexpected error: %s", err) 121 } 122 123 // Report the indexer statistics 124 // 125 stats := indexer.Stats() 126 if stats.NumFailed > 0 { 127 log.Fatalf("Indexed [%d] documents with [%d] errors", stats.NumFlushed, stats.NumFailed) 128 } else { 129 log.Printf("Successfully indexed [%d] documents", stats.NumFlushed) 130 } 131 132 // For optimal performance, consider using a third-party package for JSON decoding and HTTP transport. 133 }