From 9b204c908dd5cd2f1841b8a26a7c20626db6ebf0 Mon Sep 17 00:00:00 2001 From: Liam Date: Sat, 1 Jun 2024 23:03:34 -0400 Subject: [PATCH] More fully separate underlying search behavior from usage in application --- lib/philomena/search_policy.ex | 55 +++++++++++++++++++++ lib/philomena_query/search.ex | 87 ++++++++++++---------------------- 2 files changed, 86 insertions(+), 56 deletions(-) create mode 100644 lib/philomena/search_policy.ex diff --git a/lib/philomena/search_policy.ex b/lib/philomena/search_policy.ex new file mode 100644 index 00000000..d753026a --- /dev/null +++ b/lib/philomena/search_policy.ex @@ -0,0 +1,55 @@ +defmodule Philomena.SearchPolicy do + alias Philomena.Comments.Comment + alias Philomena.Galleries.Gallery + alias Philomena.Images.Image + alias Philomena.Posts.Post + alias Philomena.Reports.Report + alias Philomena.Tags.Tag + alias Philomena.Filters.Filter + + alias Philomena.Comments.SearchIndex, as: CommentIndex + alias Philomena.Galleries.SearchIndex, as: GalleryIndex + alias Philomena.Images.SearchIndex, as: ImageIndex + alias Philomena.Posts.SearchIndex, as: PostIndex + alias Philomena.Reports.SearchIndex, as: ReportIndex + alias Philomena.Tags.SearchIndex, as: TagIndex + alias Philomena.Filters.SearchIndex, as: FilterIndex + + @type schema_module :: Comment | Gallery | Image | Post | Report | Tag | Filter + + @doc """ + For a given schema module (e.g. `m:Philomena.Images.Image`), return the associated module + which implements the `SearchIndex` behaviour (e.g. `m:Philomena.Images.SearchIndex`). + + ## Example + + iex> SearchPolicy.index_for(Gallery) + Philomena.Galleries.SearchIndex + + iex> SearchPolicy.index_for(:foo) + ** (FunctionClauseError) no function clause matching in Philomena.SearchPolicy.index_for/1 + + """ + @spec index_for(schema_module()) :: module() + def index_for(Comment), do: CommentIndex + def index_for(Gallery), do: GalleryIndex + def index_for(Image), do: ImageIndex + def index_for(Post), do: PostIndex + def index_for(Report), do: ReportIndex + def index_for(Tag), do: TagIndex + def index_for(Filter), do: FilterIndex + + @doc """ + Return the path used to interact with the search engine. + + ## Example + + iex> SearchPolicy.opensearch_url() + "http://localhost:9200" + + """ + @spec opensearch_url :: String.t() + def opensearch_url do + Application.get_env(:philomena, :opensearch_url) + end +end diff --git a/lib/philomena_query/search.ex b/lib/philomena_query/search.ex index 13a34f44..b4960657 100644 --- a/lib/philomena_query/search.ex +++ b/lib/philomena_query/search.ex @@ -15,35 +15,10 @@ defmodule PhilomenaQuery.Search do import Ecto.Query import Elastix.HTTP - alias Philomena.Comments.Comment - alias Philomena.Galleries.Gallery - alias Philomena.Images.Image - alias Philomena.Posts.Post - alias Philomena.Reports.Report - alias Philomena.Tags.Tag - alias Philomena.Filters.Filter + # todo: fetch through compile_env? + @policy Philomena.SearchPolicy - alias Philomena.Comments.SearchIndex, as: CommentIndex - alias Philomena.Galleries.SearchIndex, as: GalleryIndex - alias Philomena.Images.SearchIndex, as: ImageIndex - alias Philomena.Posts.SearchIndex, as: PostIndex - alias Philomena.Reports.SearchIndex, as: ReportIndex - alias Philomena.Tags.SearchIndex, as: TagIndex - alias Philomena.Filters.SearchIndex, as: FilterIndex - - defp index_for(Comment), do: CommentIndex - defp index_for(Gallery), do: GalleryIndex - defp index_for(Image), do: ImageIndex - defp index_for(Post), do: PostIndex - defp index_for(Report), do: ReportIndex - defp index_for(Tag), do: TagIndex - defp index_for(Filter), do: FilterIndex - - defp opensearch_url do - Application.get_env(:philomena, :opensearch_url) - end - - @type index_module :: module() + @type schema_module :: @policy.schema_module() @type queryable :: any() @type query_body :: map() @@ -54,7 +29,7 @@ defmodule PhilomenaQuery.Search do } @type search_definition :: %{ - module: index_module(), + module: schema_module(), body: query_body(), page_number: integer(), page_size: integer() @@ -80,12 +55,12 @@ defmodule PhilomenaQuery.Search do iex> Search.create_index!(Image) """ - @spec create_index!(index_module()) :: any() + @spec create_index!(schema_module()) :: any() def create_index!(module) do - index = index_for(module) + index = @policy.index_for(module) Elastix.Index.create( - opensearch_url(), + @policy.opensearch_url(), index.index_name(), index.mapping() ) @@ -104,11 +79,11 @@ defmodule PhilomenaQuery.Search do iex> Search.delete_index!(Image) """ - @spec delete_index!(index_module()) :: any() + @spec delete_index!(schema_module()) :: any() def delete_index!(module) do - index = index_for(module) + index = @policy.index_for(module) - Elastix.Index.delete(opensearch_url(), index.index_name()) + Elastix.Index.delete(@policy.opensearch_url(), index.index_name()) end @doc ~S""" @@ -124,14 +99,14 @@ defmodule PhilomenaQuery.Search do iex> Search.update_mapping!(Image) """ - @spec update_mapping!(index_module()) :: any() + @spec update_mapping!(schema_module()) :: any() def update_mapping!(module) do - index = index_for(module) + index = @policy.index_for(module) index_name = index.index_name() mapping = index.mapping().mappings.properties - Elastix.Mapping.put(opensearch_url(), index_name, "_doc", %{properties: mapping}, + Elastix.Mapping.put(@policy.opensearch_url(), index_name, "_doc", %{properties: mapping}, include_type_name: true ) end @@ -151,13 +126,13 @@ defmodule PhilomenaQuery.Search do iex> Search.index_document(%Image{...}, Image) """ - @spec index_document(struct(), index_module()) :: any() + @spec index_document(struct(), schema_module()) :: any() def index_document(doc, module) do - index = index_for(module) + index = @policy.index_for(module) data = index.as_json(doc) Elastix.Document.index( - opensearch_url(), + @policy.opensearch_url(), index.index_name(), "_doc", data.id, @@ -181,12 +156,12 @@ defmodule PhilomenaQuery.Search do iex> Search.delete_document(image.id, Image) """ - @spec delete_document(term(), index_module()) :: any() + @spec delete_document(term(), schema_module()) :: any() def delete_document(id, module) do - index = index_for(module) + index = @policy.index_for(module) Elastix.Document.delete( - opensearch_url(), + @policy.opensearch_url(), index.index_name(), "_doc", id @@ -215,9 +190,9 @@ defmodule PhilomenaQuery.Search do Search.reindex(query, Image, batch_size: 5000) """ - @spec reindex(queryable(), index_module(), Batch.batch_options()) :: [] + @spec reindex(queryable(), schema_module(), Batch.batch_options()) :: [] def reindex(queryable, module, opts \\ []) do - index = index_for(module) + index = @policy.index_for(module) Batch.record_batches(queryable, opts, fn records -> lines = @@ -231,7 +206,7 @@ defmodule PhilomenaQuery.Search do end) Elastix.Bulk.post( - opensearch_url(), + @policy.opensearch_url(), lines, index: index.index_name(), httpoison_options: [timeout: 30_000] @@ -267,12 +242,12 @@ defmodule PhilomenaQuery.Search do Search.update_by_query(Post, query_body, [set_replacement], []) """ - @spec update_by_query(index_module(), query_body(), [replacement()], [replacement()]) :: any() + @spec update_by_query(schema_module(), query_body(), [replacement()], [replacement()]) :: any() def update_by_query(module, query_body, set_replacements, replacements) do - index = index_for(module) + index = @policy.index_for(module) url = - opensearch_url() + @policy.opensearch_url() |> prepare_url([index.index_name(), "_update_by_query"]) |> append_query_string(%{conflicts: "proceed", wait_for_completion: "false"}) @@ -355,13 +330,13 @@ defmodule PhilomenaQuery.Search do } """ - @spec search(index_module(), query_body()) :: map() + @spec search(schema_module(), query_body()) :: map() def search(module, query_body) do - index = index_for(module) + index = @policy.index_for(module) {:ok, %{body: results, status_code: 200}} = Elastix.Search.search( - opensearch_url(), + @policy.opensearch_url(), index.index_name(), [], query_body @@ -395,14 +370,14 @@ defmodule PhilomenaQuery.Search do msearch_body = Enum.flat_map(definitions, fn def -> [ - %{index: index_for(def.module).index_name()}, + %{index: @policy.index_for(def.module).index_name()}, def.body ] end) {:ok, %{body: results, status_code: 200}} = Elastix.Search.search( - opensearch_url(), + @policy.opensearch_url(), "_all", [], msearch_body @@ -440,7 +415,7 @@ defmodule PhilomenaQuery.Search do } """ - @spec search_definition(index_module(), query_body(), pagination_params()) :: + @spec search_definition(schema_module(), query_body(), pagination_params()) :: search_definition() def search_definition(module, search_query, pagination_params \\ %{}) do page_number = pagination_params[:page_number] || 1