diff --git a/lib/philomena_web/controllers/activity_controller.ex b/lib/philomena_web/controllers/activity_controller.ex index 4f13bf0d..befbfe50 100644 --- a/lib/philomena_web/controllers/activity_controller.ex +++ b/lib/philomena_web/controllers/activity_controller.ex @@ -31,7 +31,7 @@ defmodule PhilomenaWeb.ActivityController do ImageLoader.query( conn, %{range: %{first_seen_at: %{gt: "now-3d"}}}, - sorts: [%{wilson_score: :desc}, %{first_seen_at: :desc}], + sorts: &%{query: &1, sorts: [%{wilson_score: :desc}, %{first_seen_at: :desc}]}, pagination: %{page_number: :rand.uniform(6), page_size: 4} ) diff --git a/lib/philomena_web/controllers/api/json/search/image_controller.ex b/lib/philomena_web/controllers/api/json/search/image_controller.ex index 5998ff87..8d3062ce 100644 --- a/lib/philomena_web/controllers/api/json/search/image_controller.ex +++ b/lib/philomena_web/controllers/api/json/search/image_controller.ex @@ -2,7 +2,6 @@ defmodule PhilomenaWeb.Api.Json.Search.ImageController do use PhilomenaWeb, :controller alias PhilomenaWeb.ImageLoader - alias PhilomenaWeb.ImageSorter alias Philomena.Interactions alias Philomena.Images.Image import Ecto.Query @@ -10,14 +9,8 @@ defmodule PhilomenaWeb.Api.Json.Search.ImageController do def index(conn, params) do queryable = Image |> preload([:tags, :user, :intensity]) user = conn.assigns.current_user - sort = ImageSorter.parse_sort(params) - case ImageLoader.search_string(conn, params["q"], - sorts: sort.sorts, - queries: sort.queries, - constant_score: sort.constant_score, - queryable: queryable - ) do + case ImageLoader.search_string(conn, params["q"], queryable: queryable) do {:ok, {images, _tags}} -> interactions = Interactions.user_interactions(images, user) diff --git a/lib/philomena_web/controllers/gallery_controller.ex b/lib/philomena_web/controllers/gallery_controller.ex index a9e66ace..36f2f399 100644 --- a/lib/philomena_web/controllers/gallery_controller.ex +++ b/lib/philomena_web/controllers/gallery_controller.ex @@ -3,7 +3,6 @@ defmodule PhilomenaWeb.GalleryController do alias PhilomenaWeb.ImageLoader alias PhilomenaWeb.NotificationCountPlug - alias PhilomenaWeb.ImageSorter alias Philomena.Elasticsearch alias Philomena.Interactions alias Philomena.Galleries.Gallery @@ -52,12 +51,11 @@ defmodule PhilomenaWeb.GalleryController do "sd" => position_order(gallery) }) - sort = ImageSorter.parse_sort(params) + conn = %{conn | params: params} - {:ok, {images, _tags}} = - ImageLoader.search_string(conn, query, queries: sort.queries, sorts: sort.sorts) + {:ok, {images, _tags}} = ImageLoader.search_string(conn, query) - {gallery_prev, gallery_next} = prev_next_page_images(conn, query, sort) + {gallery_prev, gallery_next} = prev_next_page_images(conn, query) interactions = Interactions.user_interactions([images, gallery_prev, gallery_next], user) @@ -145,32 +143,26 @@ defmodule PhilomenaWeb.GalleryController do |> redirect(to: Routes.gallery_path(conn, :index)) end - defp prev_next_page_images(conn, query, sort) do + defp prev_next_page_images(conn, query) do limit = conn.assigns.image_pagination.page_size offset = (conn.assigns.image_pagination.page_number - 1) * limit # Inconsistency: Elasticsearch doesn't allow requesting offsets which are less than 0, # but it does allow requesting offsets which are beyond the total number of results. - prev_image = gallery_image(offset - 1, conn, query, sort) - next_image = gallery_image(offset + limit, conn, query, sort) + prev_image = gallery_image(offset - 1, conn, query) + next_image = gallery_image(offset + limit, conn, query) {prev_image, next_image} end - defp gallery_image(offset, _conn, _query, _sorts) when offset < 0, do: nil + defp gallery_image(offset, _conn, _query) when offset < 0, do: nil - defp gallery_image(offset, conn, query, sort) do + defp gallery_image(offset, conn, query) do pagination_params = %{page_number: offset + 1, page_size: 1} {:ok, {image, _tags}} = - ImageLoader.search_string( - conn, - query, - pagination: pagination_params, - queries: sort.queries, - sorts: sort.sorts - ) + ImageLoader.search_string(conn, query, pagination: pagination_params) case Enum.to_list(image) do [image] -> image diff --git a/lib/philomena_web/controllers/image/random_controller.ex b/lib/philomena_web/controllers/image/random_controller.ex index d0cac233..153078b7 100644 --- a/lib/philomena_web/controllers/image/random_controller.ex +++ b/lib/philomena_web/controllers/image/random_controller.ex @@ -31,21 +31,22 @@ defmodule PhilomenaWeb.Image.RandomController do defp query(_user, _), do: %{match_all: %{}} defp random_image_id(query, filter) do - sort = ImageSorter.parse_sort(%{"sf" => "random"}) + %{query: query, sorts: sort} = + ImageSorter.parse_sort(%{"sf" => "random"}, query) Elasticsearch.search_records( Image, %{ query: %{ bool: %{ - must: List.flatten([sort.queries, query]), + must: query, must_not: [ filter, %{term: %{hidden_from_users: true}} ] } }, - sort: sort.sorts + sort: sort }, %{page_size: 1}, Image diff --git a/lib/philomena_web/controllers/search_controller.ex b/lib/philomena_web/controllers/search_controller.ex index b2fdf2c7..8e3171bf 100644 --- a/lib/philomena_web/controllers/search_controller.ex +++ b/lib/philomena_web/controllers/search_controller.ex @@ -2,18 +2,12 @@ defmodule PhilomenaWeb.SearchController do use PhilomenaWeb, :controller alias PhilomenaWeb.ImageLoader - alias PhilomenaWeb.ImageSorter alias Philomena.Interactions def index(conn, params) do user = conn.assigns.current_user - sort = ImageSorter.parse_sort(params) - case ImageLoader.search_string(conn, params["q"], - sorts: sort.sorts, - queries: sort.queries, - constant_score: sort.constant_score - ) do + case ImageLoader.search_string(conn, params["q"]) do {:ok, {images, tags}} -> interactions = Interactions.user_interactions(images, user) diff --git a/lib/philomena_web/image_loader.ex b/lib/philomena_web/image_loader.ex index 595a65a7..399f5190 100644 --- a/lib/philomena_web/image_loader.ex +++ b/lib/philomena_web/image_loader.ex @@ -1,4 +1,5 @@ defmodule PhilomenaWeb.ImageLoader do + alias PhilomenaWeb.ImageSorter alias Philomena.Elasticsearch alias Philomena.Images.{Image, Query} alias PhilomenaWeb.TextileRenderer @@ -18,11 +19,9 @@ defmodule PhilomenaWeb.ImageLoader do end def query(conn, body, options \\ []) do - sort_queries = Keyword.get(options, :queries, []) - sort_sorts = Keyword.get(options, :sorts, [%{created_at: :desc}]) pagination = Keyword.get(options, :pagination, conn.assigns.image_pagination) queryable = Keyword.get(options, :queryable, Image |> preload(:tags)) - constant_score = Keyword.get(options, :constant_score, true) + sorts = Keyword.get(options, :sorts, &ImageSorter.parse_sort(conn.params, &1)) tags = body @@ -33,7 +32,8 @@ defmodule PhilomenaWeb.ImageLoader do user = conn.assigns.current_user filter = conn.assigns.compiled_filter filters = create_filters(conn, user, filter) - body = maybe_constant_score(body, constant_score) + + %{query: query, sorts: sort} = sorts.(body) records = Elasticsearch.search_records( @@ -41,11 +41,11 @@ defmodule PhilomenaWeb.ImageLoader do %{ query: %{ bool: %{ - must: List.flatten([body, sort_queries]), + must: query, must_not: filters } }, - sort: sort_sorts + sort: sort }, pagination, queryable @@ -95,9 +95,6 @@ defmodule PhilomenaWeb.ImageLoader do defp maybe_custom_hide(filters, _user, _param), do: filters - defp maybe_constant_score(body, false), do: body - defp maybe_constant_score(body, _), do: %{bool: %{filter: body}} - # TODO: the search parser should try to optimize queries defp search_tag_name(%{term: %{"namespaced_tags.name" => tag_name}}), do: [tag_name] defp search_tag_name(_other_query), do: [] diff --git a/lib/philomena_web/image_navigator.ex b/lib/philomena_web/image_navigator.ex index 3c3bcf50..8276af60 100644 --- a/lib/philomena_web/image_navigator.ex +++ b/lib/philomena_web/image_navigator.ex @@ -33,10 +33,11 @@ defmodule PhilomenaWeb.ImageNavigator do |> Map.merge(empty_fields()) |> ElasticsearchIndex.as_json() - sort_data = ImageSorter.parse_sort(params) + %{query: compiled_query, sorts: sort} = + ImageSorter.parse_sort(params, compiled_query) {sorts, filters} = - sort_data.sorts + sort |> Enum.map(&extract_filters(&1, image_index, rel)) |> Enum.unzip() @@ -48,7 +49,7 @@ defmodule PhilomenaWeb.ImageNavigator do %{ query: %{ bool: %{ - must: List.flatten([compiled_query, sort_data.queries, filters]), + must: List.flatten([compiled_query, filters]), must_not: [ compiled_filter, %{term: %{hidden_from_users: true}}, diff --git a/lib/philomena_web/image_sorter.ex b/lib/philomena_web/image_sorter.ex index 32a307e3..648f705e 100644 --- a/lib/philomena_web/image_sorter.ex +++ b/lib/philomena_web/image_sorter.ex @@ -16,42 +16,42 @@ defmodule PhilomenaWeb.ImageSorter do wilson_score ) - def parse_sort(params) do + def parse_sort(params, query) do sd = parse_sd(params) - parse_sf(params, sd) + parse_sf(params, sd, query) end defp parse_sd(%{"sd" => sd}) when sd in ~W(asc desc), do: sd defp parse_sd(_params), do: "desc" - defp parse_sf(%{"sf" => sf}, sd) when sf in @allowed_fields do - %{queries: [], sorts: [%{sf => sd}], constant_score: true} + defp parse_sf(%{"sf" => sf}, sd, query) when sf in @allowed_fields do + %{query: query, sorts: [%{sf => sd}]} end - defp parse_sf(%{"sf" => "_score"}, sd) do - %{queries: [], sorts: [%{"_score" => sd}], constant_score: false} + defp parse_sf(%{"sf" => "_score"}, sd, query) do + %{query: query, sorts: [%{"_score" => sd}]} end - defp parse_sf(%{"sf" => "random"}, sd) do - random_query(:rand.uniform(4_294_967_296), sd) + defp parse_sf(%{"sf" => "random"}, sd, query) do + random_query(:rand.uniform(4_294_967_296), sd, query) end - defp parse_sf(%{"sf" => <<"random:", seed::binary>>}, sd) do + defp parse_sf(%{"sf" => <<"random:", seed::binary>>}, sd, query) do case Integer.parse(seed) do {seed, _rest} -> - random_query(seed, sd) + random_query(seed, sd, query) _ -> - random_query(:rand.uniform(4_294_967_296), sd) + random_query(:rand.uniform(4_294_967_296), sd, query) end end - defp parse_sf(%{"sf" => <<"gallery_id:", gallery::binary>>}, sd) do + defp parse_sf(%{"sf" => <<"gallery_id:", gallery::binary>>}, sd, query) do case Integer.parse(gallery) do {gallery, _rest} -> %{ - queries: [], + query: query, sorts: [ %{ "galleries.position" => %{ @@ -65,31 +65,27 @@ defmodule PhilomenaWeb.ImageSorter do } } ], - constant_score: true } _ -> - %{queries: [%{match_none: %{}}], sorts: [], constant_score: true} + %{query: query, sorts: []} end end - defp parse_sf(_params, sd) do - %{queries: [], sorts: [%{"created_at" => sd}], constant_score: true} + defp parse_sf(_params, sd, query) do + %{query: query, sorts: [%{"created_at" => sd}]} end - defp random_query(seed, sd) do + defp random_query(seed, sd, query) do %{ - queries: [ - %{ - function_score: %{ - query: %{match_all: %{}}, - random_score: %{seed: seed, field: :id}, - boost_mode: :replace - } + query: %{ + function_score: %{ + query: query, + random_score: %{seed: seed, field: :id}, + boost_mode: :replace } - ], - sorts: [%{"_score" => sd}], - constant_score: true + }, + sorts: [%{"_score" => sd}] } end end