/weather-app

тестовое задание

Primary LanguageJavaScript

Chatbullet - Node.js Тестовое задание

Описание

Написать http сервер, используя express, для подключения к БД - postgres используйте pg-promise. Сервер будет отвечать только по одному url, но структура проекта должна быть рассчитана на проект с большим количеством модулей.

По запросу GET /weather/:city (где :city - это название города) должен вернуться json со следующей структурой где числа показывают температуру в городе

{
  "today": 24,
  "yesterday": 23,
  "week-average": 22
}

Предполагается что в базе есть таблица "weather", в которую каждый день складывается статистика по температуре (влажности, скорости ветра и т.п.) каждого города. Название города хранится в отдельной таблице "city".

Статистика "week-average" должна представлять среднюю температуру за текущую неделю начиная с понедельника, для её получения должен быть сделан только один запрос в базу. Все три температуры должны запрашиваться в базу параллельно.

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

Детали

Для этой задачи я решил использовать materialized view в postgres.
Этот view хранит в себе все данные по погоде по каждому городу за текущую неделю.
И строится она на основе запроса

CREATE MATERIALIZED VIEW IF NOT EXISTS week_weather_materialized_view 
    AS 
        SELECT 
            c.city_name AS city_name,
            w.temp AS temperature,
            w.probe_time AS probe_time
        FROM 
            city c JOIN weather w ON ((c.id = w.city_id))
        WHERE 
            date_trunc('week', now()) <= w.probe_time AND
            w.probe_time < date_trunc('week', now()) + '1 week'::interval;

Этот запрос оптимизирован индексом которая наложена на probe_time
Также существует крон таск которая обновляет week_weather_materialized_view каждый день в пол ночь.

REFRESH MATERIALIZED VIEW week_weather_materialized_view;

В чем преимущество этого решения?

Мы не делаем каждый раз запрос на две таблицы чтобы получить данные за неделю. Наш view максимально изолирует все данные которые нам нужны.
Для наглядности давайте предположим что каждый город отправляет нам в базу измерение за каждый час.
В итоге за день мы получаем 24 строк от каждого города.
Допустим у нас городов 100. Тогда каждый день мы сохраняем 2400 строк, а за неделю 16800. Благодаря нашей архитектуре все запросы на /weather/:city пробегаются только по этим 16800 строкам. Без этого производительность ухудшалось бы с увелечение кол-во строк

Запуск

  • npm install
  • ./start.sh

предполагается что у вас установлен docker-compose