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.
- 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
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
]
endSnap supports Elixir 1.16 or later.
Implement your own cluster module, similar to an Ecto.Repo:
defmodule MyApp.Cluster do
use Snap.Cluster, otp_app: :my_app
endConfigure 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)
endNow you can perform operations on your cluster:
{:ok, %{"count" => count}} = MyApp.Cluster.get("/my-index/_count")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.