defmodule Elastix.Document do
@moduledoc """
The document APIs expose CRUD operations on documents.
[Elastic documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs.html)
"""
import Elastix.HTTP, only: [prepare_url: 2]
alias Elastix.{HTTP, JSON}
@doc """
(Re)Indexes a document with the given `id`.
## Examples
iex> Elastix.Document.index("http://localhost:9200", "twitter", "tweet", "42", %{user: "kimchy", post_date: "2009-11-15T14:12:12", message: "trying out Elastix"})
{:ok, %HTTPoison.Response{...}}
"""
@spec index(
elastic_url :: String.t(),
index :: String.t(),
type :: String.t(),
id :: String.t(),
data :: map,
query_params :: Keyword.t()
) :: HTTP.resp()
def index(elastic_url, index_name, type_name, id, data, query_params \\ []) do
prepare_url(elastic_url, make_path(index_name, type_name, query_params, id))
|> HTTP.put(JSON.encode!(data))
end
@doc """
Indexes a new document.
## Examples
iex> Elastix.Document.index_new("http://localhost:9200", "twitter", "tweet", %{user: "kimchy", post_date: "2009-11-15T14:12:12", message: "trying out Elastix"})
{:ok, %HTTPoison.Response{...}}
"""
@spec index_new(
elastic_url :: String.t(),
index :: String.t(),
type :: String.t(),
data :: map,
query_params :: Keyword.t()
) :: HTTP.resp()
def index_new(elastic_url, index_name, type_name, data, query_params \\ []) do
prepare_url(elastic_url, make_path(index_name, type_name, query_params))
|> HTTP.post(JSON.encode!(data))
end
@doc """
Fetches a document matching the given `id`.
## Examples
iex> Elastix.Document.get("http://localhost:9200", "twitter", "tweet", "42")
{:ok, %HTTPoison.Response{...}}
"""
@spec get(
elastic_url :: String.t(),
index :: String.t(),
type :: String.t(),
id :: String.t(),
query_params :: Keyword.t()
) :: HTTP.resp()
def get(elastic_url, index_name, type_name, id, query_params \\ []) do
prepare_url(elastic_url, make_path(index_name, type_name, query_params, id))
|> HTTP.get()
end
@doc """
Fetches multiple documents matching the given `query` using the
[Multi Get API](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-multi-get.html).
"""
@spec mget(
elastic_url :: String.t(),
query :: map,
index :: String.t(),
type :: String.t(),
query_params :: Keyword.t()
) :: HTTP.resp()
def mget(elastic_url, query, index_name \\ nil, type_name \\ nil, query_params \\ []) do
path =
[index_name, type_name]
|> Enum.reject(&is_nil/1)
|> Enum.join("/")
url =
prepare_url(elastic_url, [path, "_mget"])
|> HTTP.append_query_string(query_params)
# HTTPoison does not provide an API for a GET request with a body.
HTTP.request(:get, url, JSON.encode!(query))
end
@doc """
Deletes the documents matching the given `id`.
## Examples
iex> Elastix.Document.delete("http://localhost:9200", "twitter", "tweet", "42")
{:ok, %HTTPoison.Response{...}}
"""
@spec delete(
elastic_url :: String.t(),
index :: String.t(),
type :: String.t(),
id :: String.t(),
query_params :: Keyword.t()
) :: HTTP.resp()
def delete(elastic_url, index_name, type_name, id, query_params \\ []) do
prepare_url(elastic_url, make_path(index_name, type_name, query_params, id))
|> HTTP.delete()
end
@doc """
Deletes the documents matching the given `query` using the
[Delete By Query API](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete-by-query.html).
"""
@spec delete_matching(
elastic_url :: String.t(),
index :: String.t(),
query :: map,
query_params :: Keyword.t()
) :: HTTP.resp()
def delete_matching(elastic_url, index_name, %{} = query, query_params \\ []) do
prepare_url(elastic_url, [index_name, "_delete_by_query"])
|> HTTP.append_query_string(query_params)
|> HTTP.post(JSON.encode!(query))
end
@doc """
Updates the document with the given `id`.
## Examples
iex> Elastix.Document.update("http://localhost:9200", "twitter", "tweet", "42", %{user: "kimchy", message: "trying out Elastix.Document.update/5"})
{:ok, %HTTPoison.Response{...}}
"""
@spec update(
elastic_url :: String.t(),
index :: String.t(),
type :: String.t(),
id :: String.t(),
data :: map,
query_params :: Keyword.t()
) :: HTTP.resp()
def update(elastic_url, index_name, type_name, id, data, query_params \\ []) do
elastic_url
|> prepare_url(make_path(index_name, type_name, query_params, id, "_update"))
|> HTTP.post(JSON.encode!(data))
end
@doc """
Updates the documents matching the given `query` using the
[Update By Query API](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update-by-query.html).
## Examples
iex> Elastix.Document.update_by_query("http://localhost:9200", "twitter", %{"term" => %{"user" => "kimchy"}}, %{inline: "ctx._source.user = 'kimchy updated'", lang: "painless"})
{:ok, %HTTPoison.Response{...}}
"""
@spec update_by_query(
elastic_url :: String.t(),
index :: String.t(),
query :: map,
script :: map,
query_params :: Keyword.t()
) :: HTTP.resp()
def update_by_query(elastic_url, index_name, query, script, query_params \\ []) do
elastic_url
|> prepare_url([index_name, "_update_by_query"])
|> HTTP.append_query_string(query_params)
|> HTTP.post(
JSON.encode!(%{
script: script,
query: query
})
)
end
@doc false
def make_path(index_name, type_name, query_params) do
"/#{index_name}/#{type_name}"
|> HTTP.append_query_string(query_params)
end
@doc false
def make_path(index_name, type_name, query_params, id, suffix \\ nil) do
"/#{index_name}/#{type_name}/#{id}/#{suffix}"
|> HTTP.append_query_string(query_params)
end
end