opensearch-sugar

Ruby License

A Ruby gem that wraps the opensearch-ruby client with an object-oriented shell -- collections (indexes), documents, ML models, etc -- instead of having everything runn straight off the client. I find it an easier way to think about and code interactions with OpenSearch.

The gem was a finished product before I had access to LLMs. All the original code is hand-crafted like a Seattle beer, but a variety of improvements and much of the documentation (and rbs) is AI-generated.

Of course, AI may have negated the need for nice interfaces and human-centered program design. So...YMMV in terms of usefulness.

Quick example

require "opensearch/sugar"

client = OpenSearch::Sugar::Client.new   # Pass credentials, or default uses ENV variables

index = client.open_or_create_index("products")

index.update_mappings(
  mappings: {
    properties: {
      title:    { type: "text" },
      category: { type: "keyword" },
      price:    { type: "float" }
    }
  }
)

index.index_document({ title: "Dune", category: "fiction", price: 12.99 }, "isbn-0441013597")
index.refresh   # make the document immediately searchable

results = client.search(
  index: "products",
  body: { query: { match: { title: "dune" } } }
)
puts results["hits"]["hits"].first.dig("_source", "title")
#=> "Dune"

The underlying Client object is attatched to every object created through the API, and is a paper-thin shell on a client from the official ruby gem.

See the AI-written Tutorial for a full walkthrough.

Installation

# Gemfile
gem "opensearch-sugar"
bundle install

Configuration

Connection details are read from environment variables:

Variable Used for Default
OPENSEARCH_URL Cluster URL https://localhost:9000
OPENSEARCH_HOST Cluster URL (lower priority)
OPENSEARCH_USER Basic auth user "admin"
OPENSEARCH_PASSWORD Basic auth password
OPENSEARCH_INITIAL_ADMIN_PASSWORD Basic auth password (lower priority)

Any keyword argument accepted by OpenSearch::Client.new can be passed to OpenSearch::Sugar::Client.new and will override the defaults.

Documentation

Provided by various AI models, although I've done some editing. Those things are faily good at this, even though they don't so much have a unique voice (or, rather, they all have the same unique voice)

  • Tutorial — step-by-step walkthrough building a searchable book catalog from scratch
  • How-to Guides — practical recipes for connection options, document CRUD, search, aliases, ML models, error handling, and more
  • API Reference — complete method reference for Client, Index, and Models

Tests and development

I'v never seen the point of writing unit tests for this sort of thing. I mean, a few, but anything that interacts with a server and needs to verify that The Right Thing Happened benefits from talking to the real thing. Plus I don't have to maintain the mocks. Something like VCR is appealing; maybe soon.

To run the tests:

Start a local OpenSearch cluster:

docker compose up -d

OpenSearch takes ~30 seconds to be ready. Wait until the following command succeeds before running the test suite:

❯ curl -sk https://localhost:29200 -u 'admin:Dw2F%3E*!m&psx64' | grep -q tagline && echo "Ready"

Run the specs:

bundle exec rspec

To generate a coverage report:

bundle exec rake coverage

or:

COVERAGE=true bundle exec rspec

Coverage reports are written to coverage/index.html.

To see full HTTP request/response logs during a run:

OPENSEARCH_LOG=true bundle exec rspec

Contributing

Bug reports and pull requests are welcome at https://github.com/mlibrary/opensearch-sugar. Please open an issue before submitting large changes.