Skip to content

Commit

Permalink
Merge pull request breakroom#18 from jshmrtn/search_suggest_response
Browse files Browse the repository at this point in the history
Support suggest in SearchReponse
  • Loading branch information
tomtaylor authored Jul 27, 2022
2 parents d5b1dbc + 4e31cdc commit 22d098a
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 1 deletion.
4 changes: 3 additions & 1 deletion lib/snap/search_response.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ defmodule Snap.SearchResponse do
Implements `Enumerable`, so you can iterate directly over the struct.
"""
defstruct [:took, :timed_out, :shards, :hits, :aggregations, :scroll_id, :pit_id]
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"]
Expand All @@ -23,6 +24,7 @@ defmodule Snap.SearchResponse do
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
Expand Down
27 changes: 27 additions & 0 deletions lib/snap/suggest.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
defmodule Snap.Suggest do
@moduledoc """
Represents an individual suggest dictionary from a [Search API](https://www.elastic.co/guide/en/elasticsearch/reference/current/search.html) response.
"""
defstruct ~w[
length
offset
options
text
]a

def new(response) do
%__MODULE__{
length: response["length"],
offset: response["offset"],
options: Snap.Suggest.Options.new(response["options"]),
text: response["text"]
}
end

@type t :: %__MODULE__{
length: non_neg_integer(),
offset: non_neg_integer(),
options: [Snap.Suggest.Option.t()],
text: String.t()
}
end
24 changes: 24 additions & 0 deletions lib/snap/suggest/option.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
defmodule Snap.Suggest.Option do
@moduledoc """
Represents an individual `suggest` / `options` dictionary from a [Search API](https://www.elastic.co/guide/en/elasticsearch/reference/current/search.html) response.
"""
defstruct ~w[
freq
score
text
]a

def new(response) do
%__MODULE__{
freq: response["freq"],
score: response["score"],
text: response["text"]
}
end

@type t :: %__MODULE__{
freq: integer(),
score: float(),
text: String.t()
}
end
9 changes: 9 additions & 0 deletions lib/snap/suggest/options.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
defmodule Snap.Suggest.Options do
@moduledoc """
Represents the `suggest` / `options` dictionary returned from an ElasticSearch [Search API](https://www.elastic.co/guide/en/elasticsearch/reference/current/search.html) response.
"""

def new(response), do: Enum.map(response, &Snap.Suggest.Option.new/1)

@type t :: [Snap.Suggest.Option.t()]
end
14 changes: 14 additions & 0 deletions lib/snap/suggests.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
defmodule Snap.Suggests do
@moduledoc """
Represents the `suggest` dictionary returned from an ElasticSearch [Search API](https://www.elastic.co/guide/en/elasticsearch/reference/current/search.html) response.
"""

def new(response)
def new(nil), do: nil

def new(response),
do:
Map.new(response, fn {name, suggest} -> {name, Enum.map(suggest, &Snap.Suggest.new(&1))} end)

@type t :: %{String.t() => [Snap.Suggest.t()]}
end
29 changes: 29 additions & 0 deletions test/search_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,33 @@ defmodule Snap.SearchTest do
assert first_hit.id == "1"
assert first_hit.source["title"] == "Document 1"
end

test "search with suggestion response" do
{:ok, _} = Snap.Indexes.create(Cluster, @test_index, %{})

1..5
|> Enum.map(fn i ->
doc = %{"title" => "Document #{i}"}

%Action.Index{_id: i, doc: doc}
end)
|> Snap.Bulk.perform(Cluster, @test_index, refresh: :wait_for)

query = %{
"query" => %{"match_all" => %{}},
"sort" => ["_doc"],
"suggest" => %{"title" => %{"text" => "Doument", "term" => %{"field" => "title"}}}
}

{:ok, search_response} = Search.search(Cluster, @test_index, query)
assert Enum.count(search_response) == 5

first_hit = Enum.at(search_response, 0)
assert first_hit.id == "1"
assert first_hit.source["title"] == "Document 1"

assert %Snap.SearchResponse{
suggest: %{"title" => [%{text: "doument", options: [%{text: "document"}]}]}
} = search_response
end
end

0 comments on commit 22d098a

Please sign in to comment.