Search: join on activities instead of objects
This commit is contained in:
parent
6d33c89c4d
commit
84fe16202f
|
@ -10,8 +10,11 @@ defmodule Mix.Tasks.Pleroma.Benchmark do
|
|||
start_pleroma()
|
||||
|
||||
Benchee.run(%{
|
||||
"search" => fn ->
|
||||
"With joined objects" => fn ->
|
||||
Pleroma.Activity.search(nil, "cofe")
|
||||
end,
|
||||
"With joined activities" => fn ->
|
||||
Pleroma.Activity.search(nil, "cofe", join_on: :activities)
|
||||
end
|
||||
})
|
||||
end
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
defmodule Pleroma.Activity.Search do
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Object.Fetcher
|
||||
alias Pleroma.Pagination
|
||||
alias Pleroma.User
|
||||
|
@ -15,38 +16,94 @@ defmodule Pleroma.Activity.Search do
|
|||
|
||||
def search(user, search_query, options \\ []) do
|
||||
index_type = if Pleroma.Config.get([:database, :rum_enabled]), do: :rum, else: :gin
|
||||
join_on = options[:join_on] || :activities
|
||||
limit = Enum.min([Keyword.get(options, :limit), 40])
|
||||
offset = Keyword.get(options, :offset, 0)
|
||||
author = Keyword.get(options, :author)
|
||||
|
||||
Activity
|
||||
|> Activity.with_preloaded_object()
|
||||
|> Activity.restrict_deactivated_users()
|
||||
|> restrict_public()
|
||||
base_query(join_on)
|
||||
|> restrict_deactivated(join_on)
|
||||
|> restrict_public(join_on)
|
||||
|> query_with(index_type, search_query)
|
||||
|> maybe_restrict_local(user)
|
||||
|> maybe_restrict_author(author)
|
||||
|> maybe_restrict_author(author, join_on)
|
||||
|> Pagination.fetch_paginated(%{"offset" => offset, "limit" => limit}, :offset)
|
||||
|> maybe_transform(join_on)
|
||||
|> maybe_fetch(user, search_query)
|
||||
end
|
||||
|
||||
def maybe_restrict_author(query, %User{} = author) do
|
||||
def maybe_restrict_author(query, %User{} = author, :objects) do
|
||||
from([a, o] in query,
|
||||
where: a.actor == ^author.ap_id
|
||||
)
|
||||
end
|
||||
|
||||
def maybe_restrict_author(query, _), do: query
|
||||
def maybe_restrict_author(query, %User{} = author, :activities) do
|
||||
from([o] in query,
|
||||
where: fragment("?->>'actor' = ?", o.data, ^author.ap_id)
|
||||
)
|
||||
end
|
||||
|
||||
defp restrict_public(q) do
|
||||
def maybe_restrict_author(query, _, _), do: query
|
||||
|
||||
defp restrict_public(q, :objects) do
|
||||
from([a, o] in q,
|
||||
where: fragment("?->>'type' = 'Create'", a.data),
|
||||
where: ^Pleroma.Constants.as_public() in a.recipients
|
||||
)
|
||||
end
|
||||
|
||||
defp restrict_public(q, :activities) do
|
||||
from([o, a] in q,
|
||||
where:
|
||||
fragment(
|
||||
"?->'to' \\? ? OR ?->'cc' \\? ?",
|
||||
o.data,
|
||||
^Pleroma.Constants.as_public(),
|
||||
o.data,
|
||||
^Pleroma.Constants.as_public()
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
defp base_query(:activities) do
|
||||
from(o in Object,
|
||||
as: :object,
|
||||
join: a in Activity,
|
||||
as: :activity,
|
||||
on:
|
||||
fragment(
|
||||
"(?->>'id') = COALESCE(?->'object'->>'id', ?->>'object')",
|
||||
o.data,
|
||||
a.data,
|
||||
a.data
|
||||
) and fragment("?->>'type' = 'Create'", a.data),
|
||||
preload: [create_activity: a]
|
||||
)
|
||||
end
|
||||
|
||||
defp base_query(:objects) do
|
||||
from(a in Activity, as: :activity)
|
||||
|> Activity.with_preloaded_object()
|
||||
|> where([activity: a], fragment("?->>'type' = 'Create'", a.data))
|
||||
end
|
||||
|
||||
defp restrict_deactivated(query, :activities) do
|
||||
from(
|
||||
[object: o] in query,
|
||||
where:
|
||||
fragment(
|
||||
"?->>'actor' not in (SELECT ap_id FROM users WHERE info->'deactivated' @> 'true')",
|
||||
o.data
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
defp restrict_deactivated(query, :objects) do
|
||||
Activity.restrict_deactivated_users(query)
|
||||
end
|
||||
|
||||
defp query_with(q, :gin, search_query) do
|
||||
from([a, o] in q,
|
||||
from([object: o] in q,
|
||||
where:
|
||||
fragment(
|
||||
"to_tsvector('english', ?->>'content') @@ plainto_tsquery('english', ?)",
|
||||
|
@ -57,7 +114,7 @@ defmodule Pleroma.Activity.Search do
|
|||
end
|
||||
|
||||
defp query_with(q, :rum, search_query) do
|
||||
from([a, o] in q,
|
||||
from([object: o] in q,
|
||||
where:
|
||||
fragment(
|
||||
"? @@ plainto_tsquery('english', ?)",
|
||||
|
@ -79,7 +136,15 @@ defmodule Pleroma.Activity.Search do
|
|||
end
|
||||
end
|
||||
|
||||
defp restrict_local(q), do: where(q, local: true)
|
||||
defp restrict_local(q), do: where(q, [activity: a], a.local == true)
|
||||
|
||||
defp maybe_transform(activities, :objects), do: activities
|
||||
|
||||
defp maybe_transform(objects, :activities) do
|
||||
Enum.map(objects, fn object ->
|
||||
Map.put(object.create_activity, :object, object)
|
||||
end)
|
||||
end
|
||||
|
||||
defp maybe_fetch(activities, user, search_query) do
|
||||
with true <- Regex.match?(~r/https?:/, search_query),
|
||||
|
|
|
@ -19,6 +19,7 @@ defmodule Pleroma.Object do
|
|||
|
||||
schema "objects" do
|
||||
field(:data, :map)
|
||||
has_one(:create_activity, Activity, on_delete: :nothing, foreign_key: :id)
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue