diff --git a/lib/gc_index_relay/nostr/publication_search.ex b/lib/gc_index_relay/nostr/publication_search.ex index 9e219a4..6239bb9 100644 --- a/lib/gc_index_relay/nostr/publication_search.ex +++ b/lib/gc_index_relay/nostr/publication_search.ex @@ -34,6 +34,31 @@ defmodule GcIndexRelay.Nostr.PublicationSearch do defp clamp_limit(_), do: 25 defp do_search(needles, limit) do + tag_match = metadata_tag_match(needles) + + events = + from(e in Event, + as: :event, + where: e.kind == ^@publication_kind, + where: + exists( + from(t in Tag, + where: t.event_id == parent_as(:event).id, + where: t.name in ^@search_tag_names, + where: not is_nil(t.value), + where: ^tag_match + ) + ), + order_by: [desc: e.created_at], + limit: ^limit, + preload: [:tags] + ) + |> Repo.all() + + pub_events_from_db(events) + end + + defp metadata_tag_match(needles) do spaced_needles = Enum.map(needles, &spaced_form/1) |> Enum.uniq() tag_match = @@ -48,38 +73,12 @@ defmodule GcIndexRelay.Nostr.PublicationSearch do ) end) - # Also match when the stored value's spaced form equals any spaced needle. - tag_match = - Enum.reduce(spaced_needles, tag_match, fn spaced, acc -> - dynamic( - [t], - ^acc or fragment("LOWER(TRIM(REPLACE(?, '-', ' '))) = ?", t.value, ^spaced) - ) - end) - - event_ids = - from(t in Tag, - inner_join: e in Event, - on: t.event_id == e.id, - where: e.kind == ^@publication_kind, - where: t.name in ^@search_tag_names, - where: ^tag_match, - distinct: e.id, - order_by: [desc: e.created_at], - limit: ^limit, - select: e.id - ) - |> Repo.all() - - events = - from(e in Event, - where: e.id in ^event_ids, - order_by: [desc: e.created_at], - preload: [:tags] + Enum.reduce(spaced_needles, tag_match, fn spaced, acc -> + dynamic( + [t], + ^acc or fragment("LOWER(TRIM(REPLACE(?, '-', ' '))) = ?", t.value, ^spaced) ) - |> Repo.all() - - pub_events_from_db(events) + end) end defp pub_events_from_db(events) do diff --git a/priv/repo/migrations/20260608170246_add_publication_search_tag_index.exs b/priv/repo/migrations/20260608170246_add_publication_search_tag_index.exs new file mode 100644 index 0000000..4f8bed6 --- /dev/null +++ b/priv/repo/migrations/20260608170246_add_publication_search_tag_index.exs @@ -0,0 +1,14 @@ +defmodule GcIndexRelay.Repo.Migrations.AddPublicationSearchTagIndex do + use Ecto.Migration + + @disable_ddl_transaction true + @disable_migration_lock true + + def change do + create index(:tags, [:name, :event_id], + where: "name IN ('d', 'title', 'author', 'source') AND value IS NOT NULL", + name: :tags_publication_metadata_index, + concurrently: true + ) + end +end