Skip to content

nutshell-lab/meilisearch-ex

Repository files navigation

Meilisearch-JavaScript

Meilisearch Elixir

Tests hex.pm version hex.pm docs hex.pm downloads coveralls License

🧪 The Meilisearch API client written for Elixir

Meilisearch Ex is a unofficial the Meilisearch API client based on Finch HTTP client wrapped by Tesla for Elixir developers.

Meilisearch is an open-source search engine. Learn more about Meilisearch.

Table of Contents

📖 Documentation

This readme contains all the documentation you need to start using this Meilisearch SDK.

For general information on how to use Meilisearch—such as our API reference, tutorials, guides, and in-depth articles—refer to our main documentation website.

🔧 Installation

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

def deps do
  [
    {:finch, "~> 0.14.0"},
    {:meilisearch_ex, "~> 1.1.2"}
  ]
end

meilisearch-ex officially supports elixir versions >= 1.14

Run Meilisearch

To use one of our SDKs, you must first have a running Meilisearch instance. Consult our documentation for instructions on how to download and launch Meilisearch.

Usage

There is multiple ways to define and start the Meilisearch client:

# Start finch with your app
Finch.start_link(name: :search_finch)

# Create a Meilisearch client whenever and wherever you need it.
[endpoint: "http://127.0.0.1:7700", key: "masterKey", finch: :search_finch]
|> Meilisearch.Client.new()
|> Meilisearch.Health.get()

# %Meilisearch.Health{status: "available"}

But you can also start a client alongside your application to access it whenever you need it.

Finch.start_link(name: :search_finch)

Meilisearch.start_link(:main, [
  endpoint: "http://127.0.0.1:7700",
  key: "replace_me",
  finch: :search_finch
])

:main
|> Meilisearch.client()
|> Meilisearch.Health.get()

# %Meilisearch.Health{status: "available"}

Within a Phoenix app you would do like this:

defmodule MyApp.Application do
  # ...

  @impl true
  def start(_type, _args) do
    children = [
      # ...
      {Finch, name: :search_finch},
      {Meilisearch, name: :search_admin, endpoint: "http://127.0.0.1:7700", key: "key_admin", finch: :search_finch},
      {Meilisearch, name: :search_public, endpoint: "http://127.0.0.1:7700", key: "key_public", finch: :search_finch}
    ]

    # ...
  end

  # ...
end

defmodule MyApp.MyContext do
  def create_search_index() do
    :search_admin
    |> Meilisearch.client()
    |> Meilisearch.Index.create(%{uid: "items", primaryKey: "id"})
  end

  def add_documents_to_search_index(documents) do
    :search_admin
    |> Meilisearch.client()
    |> Meilisearch.Document.create_or_replace("items", documents)
  end

  def search_document(query) do
    :search_public
    |> Meilisearch.client()
    |> Meilisearch.Search.search("items", %{q: query})
  end
end

Using another HTTP adapter

Given that the HTTP client is backed by Tesla behind the scene, you can freely use another adapter if it is more suitable for you.

def deps do
  [
    {:hackney, "~> 1.18"},
    {:meilisearch_ex, "~> 1.1.2"}
  ]
end
# Create a Meilisearch client whenever and wherever you need it.
[endpoint: "http://127.0.0.1:7700", key: "masterKey", adapter: Tesla.Adapter.Hackney]
|> Meilisearch.Client.new()
|> Meilisearch.Health.get()

# %Meilisearch.Health{status: "available"}

🎬 Getting started

Add documents

# Create the Meilisearch instance
Meilisearch.Client.new(endpoint: "http://localhost:7700", key: "masterKey")
# If the index 'movies' does not exist, Meilisearch creates it when you first add the documents.
|> Meilisearch.Document.create_or_replace(
  "movies",
  [
    %{id: 1, title: "Carol", genres: ["Romance", "Drama"]},
    %{id: 2, title: "Wonder Woman", genres: ["Action", "Adventure"]},
    %{id: 3, title: "Life of Pi", genres: ["Adventure", "Drama"]},
    %{id: 4, title: "Mad Max: Fury Road", genres: ["Adventure", "Science Fiction"]},
    %{id: 5, title: "Moana", genres: ["Fantasy", "Action"]},
    %{id: 6, title: "Philadelphia", genres: ["Drama"]}
  ]
)
# => {
#  :ok,
#  %{taskUid: 0, indexUid: "movies", status: :enqueued, type: :documentAdditionOrUpdate, enqueuedAt: ~U[..] }
# }

Tasks such as document addition always return a unique identifier. You can use this identifier taskUid to check the status (enqueued, processing, succeeded or failed) of a task.

Basic search

# Meilisearch is typo-tolerant:
Meilisearch.Client.new(endpoint: "http://localhost:7700", key: "masterKey")
|> Meilisearch.Search.search("movies", q: "philoudelphia")

Output:

{:ok, %{
  offset: 0,
  limit: 20,
  estimatedTotalHits: 1,
  processingTimeMs: 1,
  query: "philoudelphia",
  hits: [%{
    "id" => "6",
    "title" => "Philadelphia",
    "genres" => ["Drama"]
  }]
}}

🤖 Compatibility with Meilisearch

This package guarantees compatibility with version v1.x of Meilisearch, but some features may not be present. Please check the issues for more info.

💡 Learn more

The following sections in our main documentation website may interest you:

This repository also contains more examples.

⚙️ Contributing

We welcome all contributions, big and small! If you want to know more about this SDK's development workflow or want to contribute to the repo, please visit our contributing guidelines for detailed instructions.