Improve search results by implementing filtering on the Meilisearch side

You will need to rerun the `search.meilisearch index` task in order to
support this. If you do not, Akkoma will only be able to filter for
newer posts than this commit and will return an error for advanced
searches if you did not update the `filterable-attributes` attribute on
the `objects` index manually.
This commit is contained in:
itepechi 2024-05-03 05:44:07 +09:00
parent 5adae54d52
commit 1b6a18b473
Signed by: itepechi
GPG Key ID: D948CE1B5ACD0B25
2 changed files with 87 additions and 9 deletions

View File

@ -48,6 +48,16 @@ defmodule Mix.Tasks.Pleroma.Search.Meilisearch do
]
)
{:ok, _} =
meili_put(
"/indexes/objects/settings/filterable-attributes",
[
"media",
"local",
"author"
]
)
IO.puts("Created indices. Starting to insert posts.")
chunk_size = Pleroma.Config.get([Pleroma.Search.Meilisearch, :initial_indexing_chunk_size])

View File

@ -3,8 +3,9 @@ defmodule Pleroma.Search.Meilisearch do
require Pleroma.Constants
alias Pleroma.Activity
alias Pleroma.User
alias Pleroma.Search.DatabaseSearch
import Pleroma.Search.DatabaseSearch
import Ecto.Query
@behaviour Pleroma.Search.SearchBackend
@ -86,10 +87,23 @@ defmodule Pleroma.Search.Meilisearch do
only_media = Keyword.get(options, :only_media, false)
only_local = Keyword.get(options, :local, false)
filter =
[]
|> maybe_restrict_local(user, only_local)
|> maybe_restrict_author(author)
|> maybe_restrict_blocked(user)
|> maybe_restrict_following(user, following)
|> maybe_restrict_media(only_media)
res =
meili_post(
"/indexes/objects/search",
%{q: query, offset: offset, limit: limit}
%{
q: query,
offset: offset,
limit: limit,
filter: filter
}
)
with {:ok, result} <- res do
@ -100,16 +114,11 @@ defmodule Pleroma.Search.Meilisearch do
|> Activity.create_by_object_ap_id()
|> Activity.with_preloaded_object()
|> Activity.restrict_deactivated_users()
|> maybe_restrict_local(user, only_local)
|> maybe_restrict_author(author)
|> maybe_restrict_blocked(user)
|> maybe_restrict_following(user, following)
|> maybe_restrict_media(only_media)
|> maybe_fetch(user, query)
|> DatabaseSearch.maybe_fetch(user, query)
|> order_by([object: obj], desc: obj.data["published"])
|> Pleroma.Repo.all()
rescue
_ -> maybe_fetch([], user, query)
_ -> DatabaseSearch.maybe_fetch([], user, query)
end
end
end
@ -141,6 +150,9 @@ defmodule Pleroma.Search.Meilisearch do
%{
id: object.id,
content: content,
media: length(data["attachment"]) > 0,
local: Pleroma.Object.local?(object),
author: data["actor"],
ap: data["id"],
published: published |> DateTime.to_unix()
}
@ -174,4 +186,60 @@ defmodule Pleroma.Search.Meilisearch do
def remove_from_index(object) do
meili_delete!("/indexes/objects/documents/#{object.id}")
end
defp maybe_restrict_local(f, user, only_local) do
limit = Pleroma.Config.get([:instance, :limit_to_local_content], :unauthenticated)
case {only_local, limit, user} do
{true, _, _} -> restrict_local(f)
{_, :all, _} -> restrict_local(f)
{_, :unauthenticated, %User{}} -> f
{_, :unauthenticated, _} -> restrict_local(f)
{_, false, _} -> f
end
end
defp restrict_local(f) do
["local = true" | f]
end
defp maybe_restrict_author(f, %User{ap_id: ap_id}) do
[~s"author = #{Jason.encode!(ap_id)}" | f]
end
defp maybe_restrict_author(f, _), do: f
defp maybe_restrict_blocked(f, user) do
blocked_users = User.blocked_users_ap_ids(user)
case blocked_users do
[] -> f
_ -> restrict_blocked(f, blocked_users)
end
end
defp restrict_blocked(f, blocked_users) do
[~s"author NOT IN #{Jason.encode!(blocked_users)}" | f]
end
defp maybe_restrict_following(f, %User{} = user, true) do
following_users = User.following_ap_ids(user)
case following_users do
[] -> f
_ -> restrict_following(f, following_users)
end
end
defp maybe_restrict_following(f, _, _), do: f
defp restrict_following(f, following_users) do
[~s"author IN #{Jason.encode!(following_users)}" | f]
end
defp maybe_restrict_media(f, true) do
["media = true" | f]
end
defp maybe_restrict_media(f, _), do: f
end