Запрос Rails .where прикован к функции sql, есть ли способ вызвать его на результаты без преобразования их в массив? - PullRequest
0 голосов
/ 04 февраля 2020

У меня есть метод ранжирования ответов пользователей в нашей системе, который называется ranked_users

   def ranked_users
    User.joins(:responds).group(:id).select(
      "users.*, SUM(CASE WHEN answers.response != 3 THEN 1 ELSE 0 END ) avg, RANK () OVER ( 
        ORDER BY SUM(CASE WHEN answers.response != 3 THEN 1 ELSE 0 END ) DESC, CASE WHEN users.id = '#{
        current_user.id
      }' THEN 1 ELSE 0 END DESC
        ) rank"
    )
      .where('users.active = true')
      .where('answers.created_at BETWEEN ? AND ?', Time.now - 12.months, Time.now)
  end

result = ranked_users

. Затем я беру первые три с top_3 = ranked_users.limit(3)

Если пользователь не входит в тройку лидеров, я хочу добавить его с его рангом в список: user_rank = result.find_by(id: current_user.id)

Всякий раз, когда я звоню user_rank.rank, он возвращает 1. Я знаю, что это потому, что это сначала применяя предложение find_by, а затем ранжируя их. Есть ли способ обеспечить выполнение предложения find_by только по результату первого запроса? Я пытался сделать result.load.find_by(...), но у меня была та же проблема. Я мог бы преобразовать весь результат в массив, но я хочу, чтобы решение было легко масштабируемым.

1 Ответ

0 голосов
/ 04 февраля 2020

Если вы ожидаете, что в вашей рейтинговой системе будет много пользователей с большим количеством ответов и высокой нагрузкой - вы можете создать материализованное представление для запроса ранжирования с помощью (user_id, avg, rank и т. Д. c.) И refre sh. это периодически вместо расчета ранга каждый раз (скажем, несколько раз в день или даже реже). Для этого есть gem sceni c.

Вы даже можете иметь индексы по рангу и идентификатору пользователя в представлении, и ваш запрос будет из двух простых быстрых чтений из него.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...