mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-11-27 13:47:58 +01:00
somewhat fix random ordering
This commit is contained in:
parent
76b6297a8a
commit
64428907f5
8 changed files with 50 additions and 76 deletions
|
@ -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}
|
||||
)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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: []
|
||||
|
|
|
@ -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}},
|
||||
|
|
|
@ -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
|
||||
%{
|
||||
queries: [
|
||||
defp random_query(seed, sd, query) do
|
||||
%{
|
||||
query: %{
|
||||
function_score: %{
|
||||
query: %{match_all: %{}},
|
||||
query: query,
|
||||
random_score: %{seed: seed, field: :id},
|
||||
boost_mode: :replace
|
||||
}
|
||||
}
|
||||
],
|
||||
sorts: [%{"_score" => sd}],
|
||||
constant_score: true
|
||||
},
|
||||
sorts: [%{"_score" => sd}]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue