Class: OpenSearch::Sugar::Client

Inherits:
SimpleDelegator
  • Object
show all
Defined in:
lib/opensearch/sugar/client.rb,
sig/opensearch/sugar.rbs

Overview

A wrapper around OpenSearch::Client (via SimpleDelegator) that adds index management helpers and object-oriented access to indices and ML models.

All methods of the underlying OpenSearch::Client are available directly on this object via delegation. Sugar-specific additions are documented below.

Examples:

Connect and work with an index

client = OpenSearch::Sugar::Client.new
index  = client["my_index"]
index.count #=> 0

See Also:

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(host: ENV["OPENSEARCH_URL"] || ENV["OPENSEARCH_HOST"] || "https://localhost:9000", **kwargs) ⇒ Client

Creates a new OpenSearch::Sugar::Client.

Falls back to environment variables if keyword arguments are omitted:

  • hostOPENSEARCH_URLOPENSEARCH_HOST"https://localhost:9000"
  • userOPENSEARCH_USER"admin"
  • passwordOPENSEARCH_PASSWORDOPENSEARCH_INITIAL_ADMIN_PASSWORD

All keyword arguments are merged with #default_args, with explicit kwargs taking precedence.

Examples:

Connect using environment variables

client = OpenSearch::Sugar::Client.new

Connect to a specific host

client = OpenSearch::Sugar::Client.new(host: "https://search.example.com:9200")

Parameters:

  • host (String) (defaults to: ENV["OPENSEARCH_URL"] || ENV["OPENSEARCH_HOST"] || "https://localhost:9000")

    OpenSearch base URL

  • kwargs (Hash)

    Additional keyword arguments forwarded to OpenSearch::Client.new

  • host: (String) (defaults to: ENV["OPENSEARCH_URL"] || ENV["OPENSEARCH_HOST"] || "https://localhost:9000")

See Also:



57
58
59
60
61
62
63
# File 'lib/opensearch/sugar/client.rb', line 57

def initialize(host: ENV["OPENSEARCH_URL"] || ENV["OPENSEARCH_HOST"] || "https://localhost:9000", **kwargs)
  kwargs[:host] = host
  args = default_args.merge(kwargs)
  @raw_client = self.class.raw_client(**args)
  __setobj__(@raw_client)
  @models = Models.new(self)
end

Instance Attribute Details

#modelsOpenSearch::Sugar::Models (readonly)

The Models instance for ML model management on this cluster.



38
39
40
# File 'lib/opensearch/sugar/client.rb', line 38

def models
  @models
end

#raw_clientOpenSearch::Client (readonly)

The underlying raw OpenSearch::Client instance, bypassing the Sugar wrapper.

Returns:

  • (OpenSearch::Client)


34
35
36
# File 'lib/opensearch/sugar/client.rb', line 34

def raw_client
  @raw_client
end

Class Method Details

.raw_client(*args, **kwargs) ⇒ OpenSearch::Client

Creates a new raw OpenSearch client instance

Parameters:

  • args (Array)

    Arguments to pass to the OpenSearch::Client constructor

  • kwargs (Hash)

    Keyword arguments to pass to the OpenSearch::Client constructor

Returns:

  • (OpenSearch::Client)

    A new raw client instance



28
29
30
# File 'lib/opensearch/sugar/client.rb', line 28

def self.raw_client(*args, **kwargs)
  ::OpenSearch::Client.new(*args, **kwargs)
end

Instance Method Details

#[](index_name) ⇒ Index

Opens the named index and returns an Index object. Raises ArgumentError if the index does not exist.

Parameters:

  • index_name (String)

Returns:



128
129
130
# File 'lib/opensearch/sugar/client.rb', line 128

def [](index_name)
  Index.open(client: self, name: index_name)
end

#default_argsHash{Symbol => Object}

Returns the default connection arguments used when building the underlying client.

Values are drawn from environment variables where available:

  • :userOPENSEARCH_USER (default: "admin")
  • :passwordOPENSEARCH_PASSWORD or OPENSEARCH_INITIAL_ADMIN_PASSWORD
  • :hostOPENSEARCH_URL (default: "https://localhost:9000")
  • :retry_on_failure — 5
  • :request_timeout — 5 seconds
  • :logtrue
  • :tracefalse
  • :transport_options — SSL verification disabled

Returns:

  • (Hash{Symbol => Object})

    Default keyword arguments for OpenSearch::Client.new



78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/opensearch/sugar/client.rb', line 78

def default_args
  {
    user: ENV["OPENSEARCH_USER"] || "admin",
    password: ENV["OPENSEARCH_PASSWORD"] || ENV["OPENSEARCH_INITIAL_ADMIN_PASSWORD"],
    host: ENV["OPENSEARCH_URL"] || "https://localhost:9000",
    retry_on_failure: 5,
    request_timeout: 5,
    log: false,
    trace: false,
    transport_options: {ssl: {verify: false}}
  }
end

#delete_index!(index_name) ⇒ Object

Deletes the named index. Raises if the index does not exist.

Parameters:

  • index_name (String)

Returns:

  • (Object)


147
148
149
# File 'lib/opensearch/sugar/client.rb', line 147

def delete_index!(index_name)
  indices.delete(index: index_name)
end

#has_index?(name) ⇒ Boolean

Returns true if the named index exists.

Parameters:

  • name (String)

Returns:

  • (Boolean)


111
112
113
# File 'lib/opensearch/sugar/client.rb', line 111

def has_index?(name)
  indices.exists?(index: name)
end

#index_namesArray[String]

Returns the names of all indices in the cluster.

Returns:

  • (Array[String])


120
121
122
# File 'lib/opensearch/sugar/client.rb', line 120

def index_names
  cluster.state["metadata"]["indices"].keys
end

#open_or_create_index(index_name) ⇒ Index

Opens the named index if it exists; creates it otherwise.

Parameters:

  • index_name (String)

Returns:



136
137
138
139
140
# File 'lib/opensearch/sugar/client.rb', line 136

def open_or_create_index(index_name)
  Index.open(client: self, name: index_name)
rescue ArgumentError
  Index.create(client: self, name: index_name)
end

#reopen_index(index_name) ⇒ void

This method returns an undefined value.

Helper method to safely reopen an index if it's closed

Parameters:

  • index_name (String)

    The name of the index to reopen



293
294
295
296
297
298
# File 'lib/opensearch/sugar/client.rb', line 293

def reopen_index(index_name)
  indices.open(index: index_name)
rescue => open_error
  # Just log the error without raising
  warn "Warning: Failed to reopen index #{index_name}: #{open_error.message}"
end

#set_log_level(logger: "logger._root", level: "warn") ⇒ Object

Sets a cluster-level log level.

Parameters:

  • logger: (String) (defaults to: "logger._root")
  • level: (String) (defaults to: "warn")

Returns:

  • (Object)


103
104
105
# File 'lib/opensearch/sugar/client.rb', line 103

def set_log_level(logger: "logger._root", level: "warn")
  http.put("_cluster/settings", body: {persistent: {logger.to_s => level.to_s}})
end

#test_analyzer_by_definition(text:, tokenizer:, filter: [], char_filter: []) ⇒ Array[String | Array[String]]

Tests a custom transient analyzer defined inline by components, without requiring the analyzer to be registered on any index.

Parameters:

  • text: (String)
  • tokenizer: (String)
  • filter: (Array[String | Hash[untyped, untyped]]) (defaults to: [])
  • char_filter: (Array[String | Hash[untyped, untyped]]) (defaults to: [])

Returns:

  • (Array[String | Array[String]])


268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/opensearch/sugar/client.rb', line 268

def test_analyzer_by_definition(text:, tokenizer:, filter: [], char_filter: [])
  raise ArgumentError, "tokenizer cannot be nil or empty" if tokenizer.nil? || tokenizer.to_s.empty?

  body = {tokenizer: tokenizer, text: text}
  body[:filter] = filter if filter && !filter.empty?
  body[:char_filter] = char_filter if char_filter && !char_filter.empty?

  response = self.indices.analyze(body: body)

  tokens = response["tokens"]
  tokens.each_with_index.map do |token, i|
    if i > 0 && token["position"] == tokens[i - 1]["position"]
      [token["token"]]
    else
      token["token"]
    end
  end
end

#update_mappings(mappings, index_name) ⇒ Object

Applies mappings to an index (close → put_mapping → open). Raises OpenSearch::Sugar::Error on failure.

Parameters:

  • mappings (Hash[untyped, untyped])
  • index_name (String)

Returns:

  • (Object)


213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/opensearch/sugar/client.rb', line 213

def update_mappings(mappings, index_name)
  # Extract the actual OpenSearch settings from our enhanced settings object
  opensearch_mappings = if mappings.keys.map(&:to_s) == ["mappings"]
    mappings.values.first
  else
    mappings
  end
  indices.close(index: index_name)
  indices.put_mapping(index: index_name, body: opensearch_mappings)
  indices.open(index: index_name)
rescue => e
  reopen_index(index_name)
  raise OpenSearch::Sugar::Error, "Failed to update mappings for #{index_name}: #{e.message}"
end

#update_settings(settings, index_name) ⇒ Object

Applies settings to an index (close → put_settings → open). Raises OpenSearch::Sugar::Error on failure.

Parameters:

  • settings (Hash[untyped, untyped])
  • index_name (String)

Returns:

  • (Object)


176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/opensearch/sugar/client.rb', line 176

def update_settings(settings, index_name)
  # Extract the actual OpenSearch settings from our enhanced settings object
  opensearch_settings = if settings.keys.map(&:to_s) == ["settings"]
    settings.values.first
  else
    settings
  end
  indices.close(index: index_name)
  indices.put_settings(index: index_name, body: opensearch_settings)
  indices.open(index: index_name)
rescue => e
  reopen_index(index_name)
  raise OpenSearch::Sugar::Error, "Failed to update settings for #{index_name}: #{e.message}"
end