X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fsearch%2Felasticsearch.ex;h=20e03e1f0d7c40b6a7e1c44c54fd05cccb7c038f;hb=07a48b9293e4046c50b5d424d60a1bf16c7cc198;hp=f16ae58ce39842a560e43442b738b350b1b3c0f9;hpb=de60b1f3c1f1b49da757f21260a648cab0709c3f;p=akkoma diff --git a/lib/pleroma/search/elasticsearch.ex b/lib/pleroma/search/elasticsearch.ex index f16ae58ce..20e03e1f0 100644 --- a/lib/pleroma/search/elasticsearch.ex +++ b/lib/pleroma/search/elasticsearch.ex @@ -1,80 +1,91 @@ -defmodule Pleroma.Search.Elasticsearch do - @behaviour Pleroma.Search +# Akkoma: A lightweight social networking server +# Copyright © 2022-2022 Akkoma Authors +# SPDX-License-Identifier: AGPL-3.0-only - alias Pleroma.Web.MastodonAPI.StatusView +defmodule Pleroma.Search.Elasticsearch do + @behaviour Pleroma.Search.SearchBackend - defp to_es(term) when is_binary(term) do - %{ - match: %{ - content: %{ - query: term, - operator: "AND" - } - } - } - end + alias Pleroma.Activity + alias Pleroma.Object.Fetcher + alias Pleroma.Web.ActivityPub.Visibility + alias Pleroma.Search.Elasticsearch.Parsers - defp to_es({:quoted, term}), do: to_es(term) + def es_query(:activity, query, offset, limit) do + must = Parsers.Activity.parse(query) - defp to_es({:filter, ["hashtag", query]}) do %{ - term: %{ - hashtags: %{ - value: query + size: limit, + from: offset, + terminate_after: 50, + timeout: "5s", + sort: [ + "_score", + %{"_timestamp" => %{order: "desc", format: "basic_date_time"}} + ], + query: %{ + bool: %{ + must: must } } } end - defp to_es({:filter, [field, query]}) do - %{ - term: %{ - field => %{ - value: query - } - } - } + defp maybe_fetch(:activity, search_query) do + with true <- Regex.match?(~r/https?:/, search_query), + {:ok, object} <- Fetcher.fetch_object_from_id(search_query), + %Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]) do + activity + else + _ -> nil + end end - defp parse(query) do - query - |> SearchParser.parse!() - |> Enum.map(&to_es/1) - end + def search(user, query, options) do + limit = Enum.min([Keyword.get(options, :limit), 40]) + offset = Keyword.get(options, :offset, 0) - @impl Pleroma.Search - def search(%{assigns: %{user: user}} = _conn, %{q: query} = _params, _options) do - q = %{ - query: %{ - bool: %{ - must: parse(query) - } - } - } + parsed_query = + query + |> String.trim() + |> SearchParser.parse!() - IO.inspect(q) + activity_fetch_task = + Task.async(fn -> + maybe_fetch(:activity, String.trim(query)) + end) - out = Pleroma.Elasticsearch.search_activities(q) + activity_task = + Task.async(fn -> + q = es_query(:activity, parsed_query, offset, limit) - with {:ok, raw_results} <- out do - results = - raw_results - |> Map.get(:body, %{}) - |> Map.get("hits", %{}) - |> Map.get("hits", []) - |> Enum.map(fn result -> result["_id"] end) - |> Pleroma.Activity.all_by_ids_with_object() + :activities + |> Pleroma.Search.Elasticsearch.Store.search(q) + |> Enum.filter(fn x -> + x.data["type"] == "Create" && x.object.data["type"] == "Note" && + Visibility.visible_for_user?(x, user) + end) + end) - %{ - "accounts" => [], - "hashtags" => [], - "statuses" => - StatusView.render("index.json", - activities: results, - for: user, - as: :activity - ) - } - end + activity_results = Task.await(activity_task) + direct_activity = Task.await(activity_fetch_task) + + activity_results = + if direct_activity == nil do + activity_results + else + [direct_activity | activity_results] + end + + activity_results + end + + @impl true + def add_to_index(activity) do + Elasticsearch.put_document(Pleroma.Search.Elasticsearch.Cluster, activity, "activities") + end + + @impl true + def remove_from_index(object) do + Elasticsearch.delete_document(Pleroma.Search.Elasticsearch.Cluster, object, "activities") end end