-
Notifications
You must be signed in to change notification settings - Fork 26
/
search_response.ex
65 lines (53 loc) · 2.1 KB
/
search_response.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
defmodule Snap.SearchResponse do
@moduledoc """
Represents the response from ElasticSearch's [Search API](https://www.elastic.co/guide/en/elasticsearch/reference/current/search.html).
Implements `Enumerable`, so you can iterate directly over the struct.
"""
defstruct [:took, :timed_out, :shards, :hits, :suggest, :aggregations, :scroll_id, :pit_id]
def new(response) do
%__MODULE__{
took: response["took"],
timed_out: response["timed_out"],
shards: response["_shards"],
hits: Snap.Hits.new(response["hits"]),
suggest: Snap.Suggests.new(response["suggest"]),
aggregations: build_aggregations(response["aggregations"]),
scroll_id: response["_scroll_id"],
pit_id: response["pit_id"]
}
end
@type t :: %__MODULE__{
took: integer(),
timed_out: boolean(),
shards: map(),
hits: Snap.Hits.t(),
suggest: Snap.Suggests.t() | nil,
aggregations: %{String.t() => Snap.Aggregation.t()} | nil,
scroll_id: String.t() | nil,
pit_id: map() | nil
}
def build_aggregations(nil) do
nil
end
def build_aggregations(aggregations) when is_map(aggregations) do
Map.new(aggregations, fn {key, value} -> {key, Snap.Aggregation.new(value)} end)
end
defimpl Enumerable do
def reduce(_, {:halt, acc}, _fun), do: {:halted, acc}
def reduce(%Snap.SearchResponse{hits: %Snap.Hits{hits: hits}}, {:suspend, acc}, fun) do
{:suspended, acc, &reduce(%Snap.SearchResponse{hits: %Snap.Hits{hits: hits}}, &1, fun)}
end
def reduce(%Snap.SearchResponse{hits: %Snap.Hits{hits: []}}, {:cont, acc}, _fun),
do: {:done, acc}
def reduce(%Snap.SearchResponse{hits: %Snap.Hits{hits: [head | tail]}}, {:cont, acc}, fun) do
reduce(%Snap.SearchResponse{hits: %Snap.Hits{hits: tail}}, fun.(head, acc), fun)
end
def count(%Snap.SearchResponse{hits: %Snap.Hits{hits: hits}}) do
{:ok, Enum.count(hits)}
end
def member?(response, elem) do
{:ok, Enum.member?(response.hits.hits, elem)}
end
def slice(_response), do: {:error, __MODULE__}
end
end