Имеется дамп базы data.csv со следующими полями:
Date
– дата в форматеyyyymmdd
respondent
– уникальный номер респондентаSex
– пол респондента (1=М, 2=Ж)Age
– возраст респондентаWeight
– Некая статистика респондента для этого дня
Необходимо:
- Загрузить данные в таблицу СУБД SQL на ваш выбор (но не
SQLlite
) - Разработать API с одним
GET
эндпоинтом/getPercent
который будет выполнять следующий алгоритм:
-
На вход эндпоинта приходят 2 параметра:
audience1
иaudience2
:-
Аудитории будут приходить в формате SQL синтаксиса, например
Age BETWEEN 18 AND 35
илиSex = 2 AND Age >= 18
-
Для каждой из аудиторий отобрать из таблицы всех респондентов, подходящих под параметры
-
Для каждой из аудиторий взять средний Weight респондента этой аудиторий, сгруппировав по их уникальному номеру
-
Далее вычислить процент вхождения второй аудитории в первую, основываясь на среднем Weight. Пример:
- Имеем первую аудиторию, в которую входят resp1 с avg(Weight)=1, resp2 с avg(Weight)=2 и resp3 с avg(Weight)=3
- Имеем вторую аудиторию, в которую входят resp2, resp3 и resp4 с avg(Weight) = 2,3,4 соответственно
- Видим, что аудитории пересекаются респондентами resp2 и resp3, у которых avg(Weight) равен 2 и 3 (Средний Weight не может быть разным у одного и того же респондента). Значит процент вхождения второй аудитории в первую будет равен (2+3) / (1+2+3) = 0.8(3)
-
-
Предусмотреть варианты:
- Аудитории могут быть идентичными
- Аудитории могут не пересекаться вообще
- Вторая аудитория может быть подмножеством первой
- Первая аудитория может быть подмножеством второй
-
Отдать респонс в формате {‘percent’: результат}
-
Обернуть API в
Docker
контейнер -
Подготовить
docker-compose
конфиг для связки API+СУБД:- База данных должна быть создана и наполнена
- API слушает 80 порт
-
Опционально:
- Позаботиться об отказоустойчивости
- Позаботиться о быстродействии (учитывая, что данные не будут изменены ретроспективно)
- Порядок в коде –
pep8
, докстринги, тайпинг, структура проекта
Всего на задачу ушло 12 часов.
Сделано:
- развернуты докер-сворм стек, postgres dev, postgres test, api
- реализован dev stage
- реализован апи с версионированием на базе fastapi. Работает swaggher и redoc документация
- приложение полностью синхронное... но, естественно, для меня не проблема и асинхронные вызовы
- сделана интеграция с бд на базе alemic и SQLAlchemy (автомиграции, модели) - в данном случае я расширил задачу, чтобы показать, что я умею работать с данными инстурментами
- модель бд расширена мной до двух таблиц (чтобы показать концепцию crud и работу с джойнами в рав запросе)
- реализована автозагрузка данных в dev базу не через дамп, а через функционал апи sqlalchemy
- сделан базовый crud
- аналитический запрос к бд для эндпоинта реализован на чистом sql
- реализованы проверки входных данных (возраста)
- сам эдпоинт реализован в виде post-запроса с request body. Это тоже не совпадает с заданным в задаче, но тут я предлагаю просто не слать сырой sql в виде строк по апи, а реализовать нормальный защищенный запрос. В конечном счете в реальных условиях это так и было бы.
- flake8 соблюден, код аннотирован и добавлены комментарии (на нерусском)
Что не сделано:
- вообще не успел написать тесты. Задача большая, к сожалению никак не получалось по времени. Тесты могу делать любые юнит на базе pytest, с моками и любым цирком. Если надо, могу функциональное тестирование
- не выполнен mypy - обычно с mypy много возни, там сейчас выпадает небольшое количество ошибок, но если раскопать, может быть всякое. Не успел.
- быстродействие соответственно тоже не успел. Надо проверять запрос, остальное все ок
- "отказоустойчивость" без тестов естественно нет
Для запуска необходимо клонировать репозиторий и поместить в корень репозитория .env
файл следующего содержания
# postgres
POSTGRES_USER=postgres
POSTGRES_PASSWORD=mybrilliantpassword
POSTGRES_DB=okkam
POSTGRES_SERVER=okkam-postgres-dev
DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_SERVER}:5432/${POSTGRES_DB}
TEST_POSTGRES_USER=postgres
TEST_POSTGRES_PASSWORD=mybrilliantpassword
TEST_POSTGRES_DB=okkam-test
TEST_DATABASE_URL=postgresql://${TEST-POSTGRES_USER}:${TEST-POSTGRES_PASSWORD}@okkam-postgres-test:5432/${TEST-POSTGRES_DB}
Вам потребуется docker compose 3.8
и утилита make
для запуска стека.
-
Для vscode создайnt проект
code .
-
Установите
poetry
окружение и подготовьте линтер. Для этого используйтеpoetry config virtualenvs.in-project true
и командуpoetry install --with dev
.pyproject.toml
находится в папкеapi/app
Не забудьте перезапустить IDE. -
Старт и шотдаун:
make serve
make down
-
Внутри контейнера можно выполнить:
pytest -v -s -x
для тестирования- используйте
python -m IPython
для проверок кода mypy --install-types
mypy app
иflake8 app
- пересобрать отдельный сервис можно так
docker compose up -d --no-deps --build <service-name>
- docker stack
- db models
- init dev db (dump)
- init and mock test db
- alembic migration
- pgadmin for vscode dev
- crud
- api models
- logic
- endpoint
- tests
- mypy
- docs