Хитрый поиск Active Record. Запись создана между 3 часами ночи и началом_дня

У меня есть приложение для отслеживания температуры в связи с глобальным потеплением.

У меня есть база данных PG, записывающая температуры, а затем пытающаяся сравнить записи, созданные в начале_дня, до 3 часов ночи или начала_дня+180.

@today_records = Temp.where(Time.zone.now.beginning_of_day..Time.zone.now.beginning_of_day+180) работает отлично. Однако мне нужны эти записи для дней, которые не являются Date.current или Time.zone.now или Time.zone.yesterday. Это должен быть день, когда была сделана запись, которая хранится в столбце created_at И date: в таблице.

Я пробовал такие вещи, как @temps = Temp.all, затем @temps.where("created_at ‹= beginnig_of_day+180 AND created_at > begin_of_day"). Что-то вроде этого псевдокода сработало бы, если бы я мог получить правильный синтаксис и/или порядок/размещение.

В таблице есть столбцы даты, temp_high, и я пытался создать записи очень рано утром. Я знаю, что экземпляр Temp, такой как @temp.created_at.beginning_of_day+180, будет 3 часа ночи, если эта запись была создана точно в begin_of_day.

Как я могу использовать это поиск?

Моими моделями являются города и темпы, где города имеют много темпов, а темп принадлежит городу.

class City < ApplicationRecord 
    has_many :temps
end 

class Temp < ApplicationRecord
  belongs_to :city
end 

create_table "temps", force: :cascade do |t|
    t.datetime "date"
    t.integer "temp_high"
    t.integer "temp_mid"
    t.integer "temp_low"
    t.bigint "city_id", null: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.integer "sunset"
    t.index ["city_id"], name: "index_temps_on_city_id"
  end 
#routes.rb
get "/cities/temps/diff.json", to: 'temps#diff' 
#temps_controller 
 def diff 

      @cities = City.all 
      @temps = @cities.map{ |city| city.temps }  

      @hot = @temps.map{ |temp|  temp.map{ |city_temp| city_temp.try(:temp_high) } }   
      @cool = @temps.map{ |temp| temp.order(created_at: :desc).limit(3) } 
      render json: {HOTTEST: @hot, COOLEST: @cool }
    end 

update Приведенный ниже ответ был на самом деле хорошим ответом. В приложении я получаю именно то, о чем прошу: записи, созданные между 00:00 и 3:00. ОДНАКО

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

Можно ли также ввести переменную даты в запрос? Я не мастер sql и только что закончил изучение рельсов.

#<ActiveRecord::Relation [#<Temp id: 5, date: "2020-03-28 09:04:23", temp_high: 42, temp_mid: 35, temp_low: 28, city_id: 3, created_at: "2020-03-28 09:04:24", updated_at: "2020-03-28 09:04:24", sunset: 1585436723, current_temp: 35, sunset_datetime: "2020-03-28 23:05:23">]> 2.6.1 :007 > x[0].created_at Temp Load (0.8ms) SELECT "temps".* FROM "temps" WHERE "temps"."id" = $1 [["id", 5]] => Sat, 28 Mar 2020 02:04:24 MST -07:00

Когда вы работаете с записью напрямую, извлекаете ее из базы данных и спрашиваете, когда она была создана, вы получаете правильное время 02:04:24.

Мне нужно установить часовой пояс в postgresql. Postgesql работает с UTC, и rails преобразует его, как только он будет извлечен из БД.

Я позволяю рельсам преобразовывать их, а затем выполняю расчет после извлечения из базы данных. Это нормально, но я в основном работаю над этой проблемой и делаю менее прямое и более сложное сравнение между записями, а затем выполняю математические операции с записями, включая разницу и скорость (разница/время).

обновление 2

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

    @afternoon = Temp.where("created_at BETWEEN 
           date_trunc('day', created_at) + interval '11 hour'  AND 
           date_trunc('day', created_at) + interval '17 hour' ").first(5);   

     @overnight = Temp.where("created_at BETWEEN 
           date_trunc('day', created_at) + interval '0 hour'  AND 
           date_trunc('day', created_at) + interval '5 hour' ").first(5);

Этот пост предназначен для образовательных целей для других.


person swordfish    schedule 23.03.2020    source источник


Ответы (1)


Я думаю, это может работать нормально.

Temp.where("created_at BETWEEN 
            date_trunc('day', created_at) + interval '1 day' - interval '24 hour' AND 
            date_trunc('day', created_at) + interval '1 day' - interval '21 hour' ")

Если между вами не работает, вы можете поиграться с операторами >= и <.

person Int'l Man Of Coding Mystery    schedule 23.03.2020
comment
Это достаточно хорошо, чтобы поиграть, и я бы просто переместил это как ответ. запрос POSTGRESQL в поиске ActiveRecord — приятный штрих. Прямо сейчас я играю с тем, почему моя активная запись ставит отметку времени created_at для другого времени, чем это было на самом деле. Часовые пояса и различение того, что происходит под капотом, - характер работы :) Большое спасибо - person swordfish; 25.03.2020
comment
Я ненавижу иметь дело с часовыми поясами и тому подобным. Я забыл где, но я думаю, вы можете где-то установить время UTC. Я точно забыл, как с этим справиться :( - person Int'l Man Of Coding Mystery; 25.03.2020