defp rank_by_relevance(query, nil), do: query defp rank_by_relevance(query, term) when term == "", do: query defp rank_by_relevance(query, term) do from q in query, select_merge: %, order_by: [desc: fragment("relevance")] end end # lib/my_app/blog/blog.ex defmodule MyApp.Blog do import Ecto.Query alias MyApp.Repo alias MyApp.Blog.Post def search_posts(search_term, filters \ []) do Post |> search(search_term) # From plugin |> apply_filters(filters) |> order_by_relevance(search_term) |> Repo.all() end

execute(""" CREATE INDEX posts_search_vector_idx ON posts USING GIN(search_vector) """) end end # lib/my_app/search/query_builder.ex defmodule MyApp.Search.QueryBuilder do import Ecto.Query def build_search_query(schema, params) do base_query = from s in schema

json(conn, %suggestions: suggestions) end end # lib/my_app_web/live/search_live.ex defmodule MyAppWeb.SearchLive do use MyAppWeb, :live_view alias MyApp.Blog

<%= if @searching do %> <div class="mt-4"> <h3>Found @results results</h3> <div class="space-y-2"> <%= for result <- @results do %> <div class="p-4 border rounded"> <h4 class="font-bold"><%= result.title %></h4> <p><%= result.content %></p> </div> <% end %> </div> </div> <% end %> </div> """ end end # config/config.exs config :my_app, :search, language: "english", min_word_length: 2, stop_words: ["the", "a", "an", "and", "or"], highlight: true, highlight_tag: "<mark>" 10. Testing the Search # test/my_app/search_test.exs defmodule MyApp.SearchTest do use MyApp.DataCase alias MyApp.Blog alias MyApp.Blog.Post