Hex pm

Snap is an Elasticsearch/OpenSearch client. It provides a flexible, performant API on top of your Elasticsearch cluster, supporting high level features like versioned index management, while also providing a convenient interface into low level operations.

See the full API docs.

Features

  • Versioned index management with zero-downtime hotswapping (compatible with elasticsearch)
  • Streaming bulk operations
  • Connection pooling
  • Telemetry events
  • High level interface over the Multi Search API

Installation

The package can be installed by adding snap to your list of dependencies in mix.exs:

def deps do
  [
    {:snap, "~> 0.13"},
    {:finch, "~> 0.16"}, # By default, Snap uses Finch to make HTTP requests
  ]
end

Snap supports Elixir 1.16 or later.

Usage

Implement your own cluster module, similar to an Ecto.Repo:

defmodule MyApp.Cluster do
  use Snap.Cluster, otp_app: :my_app
end

Configure it:

config :my_app, MyApp.Cluster,
  url: "http://localhost:9200",
  username: "my_username",
  password: "my_password"

Then wire it into your application supervisor:

def start(_type, _args) do
  children = [
    {MyApp.Cluster, []}
  ]

  opts = [strategy: :one_for_one, name: MyApp.Supervisor]
  Supervisor.start_link(children, opts)
end

Now you can perform operations on your cluster:

{:ok, %{"count" => count}} = MyApp.Cluster.get("/my-index/_count")

Testing

See Snap.Test for details about to set up process isolated indexes to allow async testing against Snap.

If you want to test your app that uses this library, but don't want to have integration tests with a Elasticsearch instance running in you local dev environment, you can mock the responses using a custom HTTP client adapter.

Supposing you are using mox, you can do something like this:

# in test_helper.exs
Mox.defmock(HTTPClientMock, for: Snap.HTTPClient)
Mox.stub(HTTPClientMock, :child_spec, fn _config -> :skip end)

# in config/test.exs
config :my_app, MyApp.Cluster, http_client_adapter: HTTPClientMock

# in a test file
Mox.expect(HTTPClientMock, :request, fn _cluster, _method, _url, _headers, _body, _opts
  body = "{}" # valid json
  {:ok, %Snap.HTTPClient.Response{status: 200, headers: [], body: body}}
end)

See the API documentation for more advanced features.