Рельсы активной записи запроса с сортировкой и лимитом


Я пытаюсь собрать достаточно сложный запрос Active Record, и я довольно новичок в Rails.

Отношения

Вот соответствующие модельные отношения для запроса:

  • команды могут иметь многопользователей .
  • У пользователей есть столбецteam_id , чтобы отслеживать, в какой команде они находятся. Команды имеют одного администратора, который является пользователем. Это находится в столбцеadmin_id команды.
  • пользователи имеют электронную почту адрес (напр. foo@example.com).

Схема

Вот соответствующие части schema.rb:

create_table "teams", force: :cascade do |t|
  t.integer "admin_id"
end

create_table "users", force: :cascade do |t|
  t.string "email", default: "", null: false
  t.integer "team_id"
end

add_foreign_key "teams", "users", column: "admin_id"
add_foreign_key "users", "teams"

Запрос

Дано доменное имя (напр. example.com), я хотел бы найти команды, у которых есть администраторы с адресом электронной почты с этим доменным именем. Если есть несколько матчей, я хотел бы только команду с наибольшим количеством пользователей. Вот что у меня есть до сих пор:

team = Team.joins('INNER JOIN users ON admin_id = users.id')
           .where('email LIKE ?', "%example.com")
           .where(domain_sign_up: true)

Задача

Проблема с этим запросом заключается в том, что он возвращает все совпадения в виде массив. Я хотел бы упорядочить его по team.users.count, а затем вернуть только первую (с большинством пользователей) команду в качестве объекта, а не массива. Может быть, это кандидат на LEFT OUTER JOIN?

Спасибо!

2 2

2 ответа:

Попробуйте что-нибудь вроде этого

team = Team.joins('INNER JOIN users ON admin_id = users.id')
           .where('email LIKE ?', "%example.com")
           .where(domain_sign_up: true)
           .group('teams.id')
           .select('teams.*, COUNT(users.id) AS team_users_count')
           .order('COUNT(users.id) DESC')
           .first

Я изменил limit(1) на first. Кажется, что это не имеет большого смысла limit, если параметр равен 1, поэтому у вас есть Team, а не отношение одной команды.

Ответ, опубликованный Ursus, был весьма полезен, однако я закончил тем, что добавил новый столбец в команду под названием domain Для упрощения вещей, а затем использовал .left_join для заказа пользователями. Вот мой последний вопрос:

team = Team.left_joins(:users)
           .where(domain: 'example.com', domain_sign_up: true)
           .group('teams.id')
           .order('COUNT(users.id) DESC')
           .first