Я использую postgres tsearch в проекте с Rails 3.0.9.Чтобы сделать запрос tsearch, мне нужно включить дополнительный SQL в мое предложение from.Например, скажем, у меня есть эта модель:
class User < ActiveRecord::Base
has_one :profile
has_many :memberships
has_many :groups, :through => :memberships
end
Я хочу выполнить полнотекстовый поиск пользователей и их профилей.Я могу сделать это:
User.joins(:profile).where(
"(profiles.vectors @@ tsearch_query) or (users.vectors @@ tsearch_query)"
).from(
"to_tsquery('MYQUERY') as tsearch_query, users")
Это приводит к следующему SQL, и он отлично работает:
"SELECT \"users\".* FROM to_tsquery('MYQUERY') as tsearch_query, users INNER JOIN \"profiles\" ON \"profiles\".\"user_id\" = \"users\".\"id\" WHERE ((profiles.vectors @@ tsearch_query) or (users.vectors @@ tsearch_query))"
Но если я присоединяюсь к другому соединению, я получаю плохой SQL:
User.joins(:profile).where(
"(profiles.vectors @@ tsearch_query) or (users.vectors @@ tsearch_query)"
).from(
"to_tsquery('MYQUERY') as tsearch_query, users").joins(:groups)
Вот ошибка:
ActiveRecord::StatementInvalid: PGError: ERROR: missing FROM-clause entry for table "memberships" at character 108
: SELECT "users".* FROM to_tsquery('MYQUERY') as tsearch_query, users INNER JOIN "groups" ON "groups"."id" = "memberships"."group_id" WHERE AND ((profiles.vectors @@ tsearch_query) or (users.vectors @@ tsearch_query))
В этом запросе должно быть три оператора соединения.пользователи в профили, пользователи в членство и членство в группы.Включено только последнее объединение, поэтому мы получаем ошибку для ссылки на таблицу членства без предварительного присоединения к ней.
Но AR :: Relation знает об обоих соединениях:
irb(main)> _.send(:joins_values)
=> [:profile, :groups]
Я думаюпроблема заключается в добавлении этого вызова из области видимости.Если я вырежу это, я получу оба своих соединения.Например, я могу даже предоставить фиктивный вызов «от» и получить ту же ошибку:
User.joins(:profile).from( "users" ).joins(:groups)
ActiveRecord::StatementInvalid: PGError: ERROR: missing FROM-clause entry for table "memberships" at character 68
: SELECT "users".* FROM users INNER JOIN "groups" ON "groups"."id" = "memberships"."group_id"
irb(main)> _.send(:joins_values)
=> [:profile, :groups]
Удаление вызова «от», это прекрасно работает:
User.joins(:profile).joins(:groups)
irb(main)> _.to_sql
=> "SELECT \"users\".* FROM \"users\" INNER JOIN \"profiles\" ON \"profiles\".\"user_id\" = \"users\".\"id\" INNER JOIN \"memberships\" ON \"users\".\"id\" = \"memberships\".\"user_id\" INNER JOIN \"groups\" ON \"groups\".\"id\" = \"memberships\".\"group_id\"
Так что яЯ не уверен, как обойти это.
Моя конечная цель - иметь возможность выполнять поиск по пользователю и его профилю, а также ограничивать результаты по группам, в которых находится пользователь.