diff --git a/lib/philomena/elasticsearch.ex b/lib/philomena/elasticsearch.ex index f0546674..9b37d021 100644 --- a/lib/philomena/elasticsearch.ex +++ b/lib/philomena/elasticsearch.ex @@ -183,6 +183,26 @@ defmodule Philomena.Elasticsearch do results end + def msearch(definitions) do + msearch_body = + Enum.flat_map(definitions, fn def -> + [ + %{index: index_for(def.module).index_name()}, + def.body + ] + end) + + {:ok, %{body: results, status_code: 200}} = + Elastix.Search.search( + elastic_url(), + "_all", + [], + msearch_body + ) + + results["responses"] + end + def search_definition(module, elastic_query, pagination_params \\ %{}) do page_number = pagination_params[:page_number] || 1 page_size = pagination_params[:page_size] || 25 @@ -203,8 +223,7 @@ defmodule Philomena.Elasticsearch do } end - def search_results(definition) do - results = search(definition.module, definition.body) + defp process_results(results, definition) do time = results["took"] count = results["hits"]["total"]["value"] entries = Enum.map(results["hits"]["hits"], &{String.to_integer(&1["_id"]), &1}) @@ -221,6 +240,16 @@ defmodule Philomena.Elasticsearch do } end + def search_results(definition) do + process_results(search(definition.module, definition.body), definition) + end + + def msearch_results(definitions) do + Enum.map(Enum.zip(msearch(definitions), definitions), fn {result, definition} -> + process_results(result, definition) + end) + end + defp load_records_from_results(results, ecto_queries) do Enum.map(Enum.zip(results, ecto_queries), fn {page, ecto_query} -> {ids, hits} = Enum.unzip(page.entries) @@ -241,10 +270,22 @@ defmodule Philomena.Elasticsearch do page end + def msearch_records_with_hits(definitions, ecto_queries) do + load_records_from_results(msearch_results(definitions), ecto_queries) + end + def search_records(definition, ecto_query) do page = search_records_with_hits(definition, ecto_query) {records, _hits} = Enum.unzip(page.entries) %{page | entries: records} end + + def msearch_records(definitions, ecto_queries) do + Enum.map(load_records_from_results(msearch_results(definitions), ecto_queries), fn page -> + {records, _hits} = Enum.unzip(page.entries) + + %{page | entries: records} + end) + end end diff --git a/lib/philomena_web/controllers/activity_controller.ex b/lib/philomena_web/controllers/activity_controller.ex index bfee67eb..ecb4f1b5 100644 --- a/lib/philomena_web/controllers/activity_controller.ex +++ b/lib/philomena_web/controllers/activity_controller.ex @@ -35,12 +35,9 @@ defmodule PhilomenaWeb.ActivityController do pagination: %{page_number: :rand.uniform(6), page_size: 4} ) - images = Elasticsearch.search_records(images, preload(Image, :tags)) - top_scoring = Elasticsearch.search_records(top_scoring, preload(Image, :tags)) - comments = - Comment - |> Elasticsearch.search_definition( + Elasticsearch.search_definition( + Comment, %{ query: %{ bool: %{ @@ -57,7 +54,6 @@ defmodule PhilomenaWeb.ActivityController do }, %{page_number: 1, page_size: 6} ) - |> Elasticsearch.search_records(preload(Comment, [:user, image: [:tags]])) watched = if !!user do @@ -68,11 +64,12 @@ defmodule PhilomenaWeb.ActivityController do pagination: %{conn.assigns.image_pagination | page_number: 1} ) - watched_images = Elasticsearch.search_records(watched_images, preload(Image, :tags)) - - if Enum.any?(watched_images), do: watched_images + watched_images end + [images, top_scoring, comments, watched] = + multi_search(images, top_scoring, comments, watched) + featured_image = Image |> join(:inner, [i], f in ImageFeature, on: [image_id: i.id]) @@ -142,4 +139,26 @@ defmodule PhilomenaWeb.ActivityController do ) ) end + + defp multi_search(images, top_scoring, comments, nil) do + responses = + Elasticsearch.msearch_records( + [images, top_scoring, comments], + [preload(Image, :tags), preload(Image, :tags), preload(Comment, [:user, image: :tags])] + ) + + responses ++ [nil] + end + + defp multi_search(images, top_scoring, comments, watched) do + Elasticsearch.msearch_records( + [images, top_scoring, comments, watched], + [ + preload(Image, :tags), + preload(Image, :tags), + preload(Comment, [:user, image: :tags]), + preload(Image, :tags) + ] + ) + end end diff --git a/lib/philomena_web/controllers/gallery_controller.ex b/lib/philomena_web/controllers/gallery_controller.ex index 51ff2934..f50d58c8 100644 --- a/lib/philomena_web/controllers/gallery_controller.ex +++ b/lib/philomena_web/controllers/gallery_controller.ex @@ -53,21 +53,22 @@ defmodule PhilomenaWeb.GalleryController do "sd" => position_order(gallery) }) - conn = %{conn | params: params} - {:ok, {images, _tags}} = ImageLoader.search_string(conn, query) - images = Elasticsearch.search_records_with_hits(images, preload(Image, :tags)) - {gallery_prev, gallery_next} = prev_next_page_images(conn, query) + [images, gallery_prev, gallery_next] = + Elasticsearch.msearch_records_with_hits( + [images, gallery_prev, gallery_next], + [preload(Image, :tags), preload(Image, :tags), preload(Image, :tags)] + ) + interactions = Interactions.user_interactions([images, gallery_prev, gallery_next], user) watching = Galleries.subscribed?(gallery, user) - prev_image = if gallery_prev, do: [gallery_prev], else: [] - next_image = if gallery_next, do: [gallery_next], else: [] + gallery_images = + Enum.to_list(gallery_prev) ++ Enum.to_list(images) ++ Enum.to_list(gallery_next) - gallery_images = prev_image ++ Enum.to_list(images) ++ next_image gallery_json = Jason.encode!(Enum.map(gallery_images, &elem(&1, 0).id)) Galleries.clear_notification(gallery, user) @@ -81,8 +82,8 @@ defmodule PhilomenaWeb.GalleryController do layout_class: "layout--wide", watching: watching, gallery: gallery, - gallery_prev: gallery_prev, - gallery_next: gallery_next, + gallery_prev: Enum.any?(gallery_prev), + gallery_next: Enum.any?(gallery_next), gallery_images: gallery_images, images: images, interactions: interactions @@ -159,20 +160,16 @@ defmodule PhilomenaWeb.GalleryController do {prev_image, next_image} end - defp gallery_image(offset, _conn, _query) when offset < 0, do: nil + defp gallery_image(offset, _conn, _query) when offset < 0 do + Elasticsearch.search_definition(Image, %{query: %{match_none: %{}}}) + end 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) + {:ok, {image, _tags}} = ImageLoader.search_string(conn, query, pagination: pagination_params) - image = Elasticsearch.search_records_with_hits(image, preload(Image, :tags)) - - case Enum.to_list(image) do - [image] -> image - [] -> nil - end + image end defp parse_search(%{"gallery" => gallery_params}) do diff --git a/lib/philomena_web/controllers/profile_controller.ex b/lib/philomena_web/controllers/profile_controller.ex index 01413fb2..7e25bb5c 100644 --- a/lib/philomena_web/controllers/profile_controller.ex +++ b/lib/philomena_web/controllers/profile_controller.ex @@ -53,9 +53,6 @@ defmodule PhilomenaWeb.ProfileController do pagination: %{page_number: 1, page_size: 4} ) - recent_uploads = Elasticsearch.search_records(recent_uploads, preload(Image, :tags)) - recent_faves = Elasticsearch.search_records(recent_faves, preload(Image, :tags)) - tags = tags(conn.assigns.user.public_links) all_tag_ids = @@ -78,8 +75,8 @@ defmodule PhilomenaWeb.ProfileController do recent_artwork = recent_artwork(conn, tags) recent_comments = - Comment - |> Elasticsearch.search_definition( + Elasticsearch.search_definition( + Comment, %{ query: %{ bool: %{ @@ -97,17 +94,10 @@ defmodule PhilomenaWeb.ProfileController do }, %{page_size: 3} ) - |> Elasticsearch.search_records(preload(Comment, user: [awards: :badge], image: :tags)) - |> Enum.filter(&Canada.Can.can?(current_user, :show, &1.image)) - - recent_comments = - recent_comments - |> TextileRenderer.render_collection(conn) - |> Enum.zip(recent_comments) recent_posts = - Post - |> Elasticsearch.search_definition( + Elasticsearch.search_definition( + Post, %{ query: %{ bool: %{ @@ -123,8 +113,26 @@ defmodule PhilomenaWeb.ProfileController do }, %{page_size: 6} ) - |> Elasticsearch.search_records(preload(Post, user: [awards: :badge], topic: :forum)) - |> Enum.filter(&Canada.Can.can?(current_user, :show, &1.topic)) + + [recent_uploads, recent_faves, recent_artwork, recent_comments, recent_posts] = + Elasticsearch.msearch_records( + [recent_uploads, recent_faves, recent_artwork, recent_comments, recent_posts], + [ + preload(Image, :tags), + preload(Image, :tags), + preload(Image, :tags), + preload(Comment, user: [awards: :badge], image: :tags), + preload(Post, user: [awards: :badge], topic: :forum) + ] + ) + + recent_posts = Enum.filter(recent_posts, &Canada.Can.can?(current_user, :show, &1.topic)) + + recent_comments = + recent_comments + |> Enum.filter(&Canada.Can.can?(current_user, :show, &1.image)) + |> TextileRenderer.render_collection(conn) + |> Enum.zip(recent_comments) about_me = TextileRenderer.render_one(%{body: user.description || ""}, conn) @@ -214,7 +222,9 @@ defmodule PhilomenaWeb.ProfileController do defp tags([]), do: [] defp tags(links), do: Enum.map(links, & &1.tag) |> Enum.reject(&is_nil/1) - defp recent_artwork(_conn, []), do: [] + defp recent_artwork(_conn, []) do + Elasticsearch.search_definition(Image, %{query: %{match_none: %{}}}) + end defp recent_artwork(conn, tags) do {images, _tags} = @@ -224,7 +234,7 @@ defmodule PhilomenaWeb.ProfileController do pagination: %{page_number: 1, page_size: 4} ) - Elasticsearch.search_records(images, preload(Image, :tags)) + images end defp set_admin_metadata(conn, _opts) do diff --git a/lib/philomena_web/templates/profile/user_link/show.html.slime b/lib/philomena_web/templates/profile/user_link/show.html.slime index 57af0500..621dd685 100644 --- a/lib/philomena_web/templates/profile/user_link/show.html.slime +++ b/lib/philomena_web/templates/profile/user_link/show.html.slime @@ -51,7 +51,7 @@ h3 Visibility h3 Associated tag = if @user_link.tag do - p + .tag-list = render PhilomenaWeb.TagView, "_tag.html", tag: @user_link.tag, conn: @conn - else p There is no tag associated with this link. diff --git a/lib/philomena_web/views/gallery_view.ex b/lib/philomena_web/views/gallery_view.ex index 3796c1ed..6ba4e2a5 100644 --- a/lib/philomena_web/views/gallery_view.ex +++ b/lib/philomena_web/views/gallery_view.ex @@ -12,10 +12,10 @@ defmodule PhilomenaWeb.GalleryView do |> Enum.join(" ") end - def sortable_prev(list, nil), do: list + def sortable_prev(list, false), do: list def sortable_prev(list, _), do: ["js-sortable-has-prev" | list] - def sortable_next(list, nil), do: list + def sortable_next(list, false), do: list def sortable_next(list, _), do: ["js-sortable-has-next" | list] def show_subscription_link?(%{id: id}, %{id: id}), do: false