Rails `where` за время меньше запросов
Настройка
Метод Rails where
может принимать диапазон в хеше, чтобы сгенерировать запрос, который будет искать значение, находящееся в пределах диапазона. Например:
User.where(cash_money: 10..1000)
#=> SELECT `users`.* FROM `users` WHERE (`users`.`cash_money` BETWEEN 10 AND 1000)
Это также можно использовать с отметками времени, например
User.where(last_deposit: 10.days.ago..1000.days.ago)
#=> SELECT `users`.* FROM `users` WHERE (`users`.`last_deposit` BETWEEN '2014-05-19 14:42:36' AND '2011-09-02 14:42:36')
Я обнаружил, что вы можете сделать простой, чем или больше, чем с числами, используя синтаксис хэша, подобный этому
User.where(cash_money: 10..Float::INFINITY)
#=> SELECT `users`.* FROM `users` WHERE (`users`.`cash_money` >= 10)
и то же самое можно сделать с помощью -Float::INFINITY
меньше запросов.
Вопрос
Есть ли способ сделать это с помощью временных меток, чтобы я мог получить такой запрос:
SELECT `users`.* FROM `users` WHERE (`users`.`last_deposit` >= '2014-05-19 14:42:36')
Я не могу использовать Float::INFINITY
или Date::Infinity
с диапазоном, поскольку оба они имеют ошибку с ArgumentError: bad value for range
.
Текущее простое решение
User.where('`users`.`last_deposit` >= ?', 10.days.ago)
будет генерировать тот же SQL, но если это можно сделать с объектами, отличными от строк, я бы хотел сделать это.
Ответ на потенциальный (мех)
Это отвратительно, но это можно сделать с диапазонами с использованием Time.at(0)
и Time.at(Float::MAX)
. У меня такое чувство, что это может привести к столь же отвратительным SQL-запросам.
Ответы
Ответ 1
Он не выглядит так, как если бы использовался базовый синтаксис хеша where
для генерации большего или меньшего, чем запрос для временных меток. Самый простой и читаемый способ изложен в моем вопросе в разделе Current Simple Solution
.
Другой способ сделать это - использовать AREL, но вы должны делать некоторые менее часто встречающиеся вызовы. Сначала вы можете получить дескриптор таблицы ARel AR, получить доступ к столбцу, передать результат больше, чем gt
, больше или равно gteq
, меньше, чем lt
, и/или меньше или равный lteq
с аргументом where
.
В ситуации выше это будет сделано следующим образом:
last_deposit_column = User.arel_table[:last_deposit]
last_deposit_over_ten_days_ago = last_deposit_column.gteq(10.days.ago)
User.where(last_deposit_over_ten_days_ago)
Ответ 2
Вы попробовали это?:
User.where(last_deposit: Time.at(0)...10.days.ago)
SQL:
SELECT `users`.* FROM `users` WHERE (`users`.`last_deposit` >= '1970-01-01 00:00:00' AND `users`.`last_deposit` < '2015-01-10 17:15:19')
Ответ 3
Вам нужно использовать соответствующую бесконечность. Временная метка DateTime
не a Date
. Используйте вместо DateTime::Infinity.new
или DateTime::Infinity.new(-1)
для отрицательного бесконечного.
Связанный: Есть ли способ выразить "Бесконечное время" в Ruby?
Ответ 4
Попробуйте следующее:
User.where(last_deposit.gt(10.days.ago))