Ошибка ОШИБКА (undefined_table) при полнотекстовом поиске с Ecto и PostgreSQL

#postgresql #elixir #phoenix-framework #ecto

#postgresql #elixir #phoenix-framework #ecto

Вопрос:

Я пытаюсь реализовать очень простой полнотекстовый поиск в моем приложении Phoenix, используя Ecto и PostgreSQL. На основе одного примера и документов PostgreSQL, которые у меня есть в моем контроллере:

 def search(conn, %{"q" => para}) do
    search = User |> User.search(para) |> Repo.all
    render(conn, "search.html", search: search)
  end
  

и в моем файле «model» (вместе с определением User полей):

 def search(query, search_term) do
    (from u in query,
    where: fragment("to_tsvector(u.name) @@ plainto_tsquery(?)", ^search_term),
    order_by: fragment("ts_rank(to_tsvector(u.name), plainto_tsquery(?)) DESC", ^search_term))
  end
  

Я получаю эту ошибку:

 ERROR (undefined_table): missing FROM-clause entry for table "u"
  

Разве from u in query недостаточно ( name является одним из User полей)?

Ответ №1:

Вы u.name не можете так использовать. u это просто имя, которое существует в Elixir при компиляции запроса в SQL. Он переименовывается во время компиляции. Вам нужно добавить еще ? fragment один и передать u.name для этого:

 def search(query, search_term) do
  from u in query,
    where: fragment("to_tsvector(?) @@ plainto_tsquery(?)", u.name, ^search_term),
    order_by: fragment("ts_rank(to_tsvector(?), plainto_tsquery(?)) DESC", u.name, ^search_term)
end
  

Комментарии:

1. Это работает, но теперь при попытке доступа <%=@search%> к моему шаблону я получаю другую ошибку, потому что я получаю все данные из модели : lists in Phoenix.HTML and templates may only contain integers representing bytes, binaries or other lists, got invalid entry: %MyProj.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">, contacts: "Tlm: 22222222", details: nil, facebook: nil, id: 16, inserted_at: #Ecto.DateTime<2016-10-03 13:55:30>, name: "blabla", updated_at: #Ecto.DateTime<2016-10-03 13:55:30>, web_page: nil} . Я безуспешно пытался использовать точечную нотацию…

2. @search это список. Что именно вы хотите распечатать из списка? Вы можете использовать что-то вроде for : <%= for user <- @search do %> <%= user.name %> <% end %> .

3. Правильно! Я просто слишком расстроен, чтобы мыслить здраво! Первый раз с SQL и чувствую, что я никогда этого не пойму 🙂 Я собираюсь открыть несколько более сфокусированных вопросов, поскольку я застрял. Спасибо, Догберт!