Add initial documentation for MongoDB, Neo4j, pgAdmin, PostgreSQL, and Redis in Docker
This commit is contained in:
commit
699dd0d18f
93
README.md
Normal file
93
README.md
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
# Практикум: «Работа с реляционными и нереляционными СУБД»
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### Установка Docker Desktop на Windows
|
||||||
|
|
||||||
|
- Требования:
|
||||||
|
- Windows 10 21H2/22H2 (19044/19045) или Windows 11
|
||||||
|
- Включенная виртуализация в BIOS/UEFI (Intel VT-x/AMD-V)
|
||||||
|
- Рекомендовано: WSL 2
|
||||||
|
|
||||||
|
- Включить компоненты Windows (PowerShell от имени администратора):
|
||||||
|
```powershell
|
||||||
|
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
|
||||||
|
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
|
||||||
|
```
|
||||||
|
Перезагрузите компьютер.
|
||||||
|
|
||||||
|
- Установить ядро WSL2 (если требуется):
|
||||||
|
```powershell
|
||||||
|
wsl --install --no-distribution
|
||||||
|
wsl --update
|
||||||
|
```
|
||||||
|
|
||||||
|
- Скачать и установить Docker Desktop: см. страницу загрузки [Docker Desktop for Windows](https://www.docker.com/products/docker-desktop/). Во время установки оставьте галочку «Use WSL 2 based engine».
|
||||||
|
|
||||||
|
- Первый запуск и базовые настройки:
|
||||||
|
- Войти с Docker ID (или пропустить для локальной работы)
|
||||||
|
- Settings → General: убедитесь, что «Use the WSL 2 based engine» включен
|
||||||
|
- Settings → Resources → WSL Integration: включите интеграцию для нужных дистрибутивов WSL
|
||||||
|
|
||||||
|
- Проверка установки:
|
||||||
|
```powershell
|
||||||
|
docker version
|
||||||
|
docker run hello-world
|
||||||
|
docker run --rm -it alpine:3.20 echo "Docker OK"
|
||||||
|
```
|
||||||
|
|
||||||
|
## PostgreSQL with Docker
|
||||||
|
|
||||||
|
- **Установите Docker Desktop**: Убедитесь, что Docker установлен и запущен на вашем компьютере.
|
||||||
|
|
||||||
|
- **Скачать образ Postgres**:
|
||||||
|
```bash
|
||||||
|
docker pull postgres:16
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Запустить контейнер PostgreSQL**:
|
||||||
|
```bash
|
||||||
|
docker run --name pg-local -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=appdb -p 5432:5432 -v pgdata:/var/lib/postgresql/data -d postgres:16
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Проверить, что контейнер запущен**:
|
||||||
|
```bash
|
||||||
|
docker ps
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Подключение к PostgreSQL**:
|
||||||
|
- С хоста через psql (Windows PowerShell, macOS, Linux):
|
||||||
|
```bash
|
||||||
|
psql -h localhost -p 5432 -U postgres -d appdb
|
||||||
|
```
|
||||||
|
При запросе пароля введите: `postgres`.
|
||||||
|
- URI‑строка подключения (подходит для приложений/GUI‑клиентов):
|
||||||
|
```
|
||||||
|
postgres://postgres:postgres@localhost:5432/appdb
|
||||||
|
```
|
||||||
|
- Через psql внутри контейнера:
|
||||||
|
```bash
|
||||||
|
docker exec -it pg-local psql -U postgres -d appdb
|
||||||
|
```
|
||||||
|
- Параметры для GUI‑клиента (pgAdmin, DBeaver и др.):
|
||||||
|
- Host: `localhost`
|
||||||
|
- Port: `5432`
|
||||||
|
- User: `postgres`
|
||||||
|
- Password: `postgres`
|
||||||
|
- Database: `appdb`
|
||||||
|
- Быстрая проверка подключения (внутри psql):
|
||||||
|
```sql
|
||||||
|
SELECT version();
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Полезные команды**:
|
||||||
|
```bash
|
||||||
|
# Остановить / запустить / удалить контейнер
|
||||||
|
docker stop pg-local
|
||||||
|
docker start pg-local
|
||||||
|
docker rm -f pg-local
|
||||||
|
|
||||||
|
# Удалить том с данными (необратимо)
|
||||||
|
docker volume rm pgdata
|
||||||
|
```
|
||||||
|
|
||||||
111
mongo.md
Normal file
111
mongo.md
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
# MongoDB: установка и базовое использование
|
||||||
|
|
||||||
|
Краткая инструкция по установке MongoDB на Windows и запуску в Docker, подключению через `mongosh` и базовым операциям.
|
||||||
|
|
||||||
|
## Вариант A: Docker (рекомендуется для практикума)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Запуск MongoDB (порт 27017), создание пользователя root
|
||||||
|
# Замените StrongPass! на свой пароль
|
||||||
|
|
||||||
|
docker run -d --name mongo -p 27017:27017 -e MONGO_INITDB_ROOT_USERNAME=root -e MONGO_INITDB_ROOT_PASSWORD=StrongPass! -v mongo_data:/data/db mongo:7
|
||||||
|
```
|
||||||
|
|
||||||
|
Подключение `mongosh` (если установлен локально):
|
||||||
|
```bash
|
||||||
|
mongosh "mongodb://root:StrongPass!@localhost:27017/?authSource=admin"
|
||||||
|
```
|
||||||
|
|
||||||
|
Создание приложения БД/пользователя:
|
||||||
|
```javascript
|
||||||
|
use appdb
|
||||||
|
|
||||||
|
db.createUser({
|
||||||
|
user: "appuser",
|
||||||
|
pwd: "AppUserPass!",
|
||||||
|
roles: [ { role: "readWrite", db: "appdb" } ]
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Проверка записи/чтения:
|
||||||
|
```javascript
|
||||||
|
db.items.insertOne({ name: "sensor-1", type: "pressure", value: 28.5 })
|
||||||
|
db.items.find()
|
||||||
|
```
|
||||||
|
|
||||||
|
Останов/старт/удаление контейнера:
|
||||||
|
```bash
|
||||||
|
docker stop mongo && docker start mongo && docker rm -f mongo
|
||||||
|
```
|
||||||
|
|
||||||
|
## Полезные команды `mongosh`
|
||||||
|
```javascript
|
||||||
|
// Показать базы/коллекции
|
||||||
|
show dbs
|
||||||
|
use appdb
|
||||||
|
show collections
|
||||||
|
|
||||||
|
// CRUD
|
||||||
|
db.devices.insertMany([{name:"compressor-A", status:"online"},{name:"compressor-B", status:"offline"}])
|
||||||
|
db.devices.find({status:"online"})
|
||||||
|
db.devices.updateOne({name:"compressor-B"}, {$set: {status:"online"}})
|
||||||
|
db.devices.deleteOne({name:"compressor-A"})
|
||||||
|
|
||||||
|
// Индекс
|
||||||
|
db.devices.createIndex({status:1})
|
||||||
|
|
||||||
|
// Фильтры (сравнение, логика, диапазоны)
|
||||||
|
db.devices.find({status: {$in: ["online", "maintenance"]}})
|
||||||
|
db.readings.find({value: {$gte: 10, $lt: 50}})
|
||||||
|
db.readings.find({$and: [{type:"pressure"}, {value: {$gt: 100}}]})
|
||||||
|
|
||||||
|
// Проекция полей (включение/исключение)
|
||||||
|
db.devices.find({}, {name:1, status:1, _id:0})
|
||||||
|
|
||||||
|
// Сортировка, лимит, пропуск
|
||||||
|
db.readings.find({type:"temperature"}).sort({timestamp:-1}).limit(10)
|
||||||
|
db.readings.find({type:"temperature"}).sort({timestamp:1}).skip(20).limit(10)
|
||||||
|
|
||||||
|
// Составной запрос: фильтр + проекция + сортировка + пагинация
|
||||||
|
db.devices.find({status:"online"}, {name:1, status:1, _id:0}).sort({name:1}).skip(0).limit(5)
|
||||||
|
|
||||||
|
// Поддокументы/массивы
|
||||||
|
db.wells.insertOne({name:"Well-1001", sensors:[{type:"pressure", value:2800},{type:"temperature", value:85}]})
|
||||||
|
db.wells.find({"sensors.type":"pressure", "sensors.value": {$gt: 2500}})
|
||||||
|
|
||||||
|
|
||||||
|
// Встроенные (embedded) документы: вложенные поля, запросы и обновления
|
||||||
|
db.wells.insertOne({
|
||||||
|
name: "Well-1002",
|
||||||
|
location: { field: "Permian", coords: { lat: 31.77, lon: -102.39 } },
|
||||||
|
equipment: {
|
||||||
|
compressor: { model: "CMP-900", status: "online" },
|
||||||
|
valve: { type: "pressure_relief", lastService: ISODate("2025-10-01") }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Поиск по вложенным полям (dot-notation)
|
||||||
|
db.wells.find({ "location.field": "Permian", "equipment.compressor.status": "online" }, { _id:0, name:1 })
|
||||||
|
|
||||||
|
// Проекция поддокумента
|
||||||
|
db.wells.find({ name: "Well-1002" }, { _id:0, equipment:1 })
|
||||||
|
|
||||||
|
// Обновление вложенного поля
|
||||||
|
db.wells.updateOne(
|
||||||
|
{ name: "Well-1002" },
|
||||||
|
{ $set: { "equipment.compressor.status": "maintenance" } }
|
||||||
|
)
|
||||||
|
|
||||||
|
// Добавление нового вложенного поля, если его не было
|
||||||
|
db.wells.updateOne(
|
||||||
|
{ name: "Well-1002" },
|
||||||
|
{ $set: { "equipment.sensorHub": { firmware: "1.2.3", ports: 8 } } }
|
||||||
|
)
|
||||||
|
|
||||||
|
// Удаление вложенного поля
|
||||||
|
db.wells.updateOne(
|
||||||
|
{ name: "Well-1002" },
|
||||||
|
{ $unset: { "equipment.valve.lastService": "" } }
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
55
neo4j.md
Normal file
55
neo4j.md
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# Neo4j в Docker: установка и базовое использование
|
||||||
|
|
||||||
|
Краткая инструкция по запуску Neo4j в Docker, подключению к Browser/bolt и базовым операциям.
|
||||||
|
|
||||||
|
## Запуск Neo4j (одной командой)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Откроет порты 7474 (HTTP)
|
||||||
|
|
||||||
|
docker run -d --name neo4j -p 7474:7474 -e NEO4J_AUTH=neo4j/neo4j -v neo4j_data:/data -v neo4j_logs:/logs -v neo4j_import:/var/lib/neo4j/import -v neo4j_plugins:/plugins neo4j:5
|
||||||
|
```
|
||||||
|
|
||||||
|
- Откройте `http://localhost:7474` (Neo4j Browser)
|
||||||
|
- Подключение по bolt: `bolt://localhost:7687`
|
||||||
|
|
||||||
|
## Управление контейнером
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker restart neo4j
|
||||||
|
|
||||||
|
docker stop neo4j
|
||||||
|
|
||||||
|
docker rm -f neo4j
|
||||||
|
```
|
||||||
|
|
||||||
|
## Переменные окружения (часто используемые)
|
||||||
|
|
||||||
|
- `NEO4J_AUTH=neo4j/<password>` — пароль пользователя `neo4j` (или `none` для тестов)
|
||||||
|
|
||||||
|
|
||||||
|
## Подключение из CLI (cypher-shell)
|
||||||
|
|
||||||
|
Если установлен `cypher-shell` на хосте:
|
||||||
|
```bash
|
||||||
|
cypher-shell -u neo4j -p MyStrongPassword! -a bolt://localhost:7687
|
||||||
|
```
|
||||||
|
|
||||||
|
Или из контейнера:
|
||||||
|
```bash
|
||||||
|
docker exec -it neo4j cypher-shell -u neo4j -p MyStrongPassword!
|
||||||
|
```
|
||||||
|
|
||||||
|
## Базовые команды Cypher (пример)
|
||||||
|
|
||||||
|
```cypher
|
||||||
|
// Создать узел
|
||||||
|
CREATE (:Person {name: "Alice", age: 30});
|
||||||
|
|
||||||
|
// Найти узлы
|
||||||
|
MATCH (p:Person) RETURN p LIMIT 10;
|
||||||
|
|
||||||
|
// Создать связь
|
||||||
|
MATCH (a:Person {name:"Alice"})
|
||||||
|
CREATE (a)-[:KNOWS]->(:Person {name:"Bob"});
|
||||||
|
```
|
||||||
46
pgadmin.md
Normal file
46
pgadmin.md
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# pgAdmin (Docker): установка и подключение к существующему PostgreSQL
|
||||||
|
|
||||||
|
Инструкция по запуску pgAdmin 4 в Docker и подключению к контейнеру Postgres `pg-local`.
|
||||||
|
|
||||||
|
## 1) Запуск pgAdmin в Docker
|
||||||
|
|
||||||
|
- Вариант по умолчанию (порт 5050):
|
||||||
|
```bash
|
||||||
|
docker run -d --name pgadmin -e PGADMIN_DEFAULT_EMAIL=admin@example.com -e PGADMIN_DEFAULT_PASSWORD=admin -p 5050:80 -v pgadmin_data:/var/lib/pgadmin dpage/pgadmin4:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
- Открыть интерфейс:
|
||||||
|
- Браузер: http://localhost:5050
|
||||||
|
- Войти с значениями `PGADMIN_DEFAULT_EMAIL` и `PGADMIN_DEFAULT_PASSWORD`.
|
||||||
|
|
||||||
|
## 2) Подключение к текущему Postgres (`pg-local`)
|
||||||
|
|
||||||
|
У вас уже запущен контейнер PostgreSQL (см. README):
|
||||||
|
```bash
|
||||||
|
docker run --name pg-local -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=appdb -p 5432:5432 -v pgdata:/var/lib/postgresql/data -d postgres:16
|
||||||
|
```
|
||||||
|
|
||||||
|
### Подключение через опубликованный порт хоста..
|
||||||
|
- В pgAdmin: Add New Server → вкладка General:
|
||||||
|
- Name: `Local Postgres`
|
||||||
|
- Вкладка Connection:
|
||||||
|
- Host: `localhost` (если pgAdmin установлен на хосте)
|
||||||
|
- Host: `host.docker.internal` (если pgAdmin запущен в Docker без общей сети)
|
||||||
|
- Port: `5432`
|
||||||
|
- Maintenance DB: `appdb` (или `postgres`)
|
||||||
|
- Username: `postgres`
|
||||||
|
- Password: `postgres`
|
||||||
|
- Save Password: включить (по желанию)
|
||||||
|
- Сохранить. Подключение установится сразу.
|
||||||
|
|
||||||
|
Примечание: pgAdmin открыт в вашем браузере, поэтому доступ к `localhost:5432` идёт с вашей машины.
|
||||||
|
|
||||||
|
## 3) Проверка соединения
|
||||||
|
После добавления сервера в pgAdmin, раскройте дерево:
|
||||||
|
- Servers → ваш сервер → Databases → `appdb` → Schemas → `public` → Tables
|
||||||
|
- Откройте Query Tool и выполните:
|
||||||
|
```sql
|
||||||
|
SELECT version();
|
||||||
|
SELECT current_database(), current_user, now();
|
||||||
|
```
|
||||||
|
|
||||||
314
postgres.md
Normal file
314
postgres.md
Normal file
@ -0,0 +1,314 @@
|
|||||||
|
# Работа с PostgreSQL
|
||||||
|
|
||||||
|
Минимальные команды для работы с одной таблицей: подключение, создание с первичным ключом, CRUD и основные команды ALTER.
|
||||||
|
|
||||||
|
## Подключение (контейнер Docker)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec -it pg-local psql -U postgres -d appdb
|
||||||
|
```
|
||||||
|
## Важные slash-команды psql
|
||||||
|
|
||||||
|
```psql
|
||||||
|
\? -- помощь по psql
|
||||||
|
\l -- список баз данных
|
||||||
|
\c appdb -- подключиться к базе appdb
|
||||||
|
\dt -- список таблиц
|
||||||
|
\du -- список ролей/пользователей
|
||||||
|
\dn -- список схем
|
||||||
|
\d contacts -- описание таблицы contacts
|
||||||
|
\i file.sql -- выполнить SQL-скрипт из файла
|
||||||
|
\q -- выход
|
||||||
|
```
|
||||||
|
Выйти: `\q`.
|
||||||
|
|
||||||
|
## Рекомендации по именованию (best practices)
|
||||||
|
|
||||||
|
- Таблицы и столбцы: `snake_case`, английские названия; будьте последовательны (единственное или множественное число — выберите и придерживайтесь).
|
||||||
|
- Первичный ключ: как правило `id` типа `BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY`.
|
||||||
|
- Внешние ключи: `<referenced_table>_id`, тот же тип, что и PK ссылочной таблицы.
|
||||||
|
- Метки времени: `created_at`, `updated_at` типа `TIMESTAMPTZ`; задавайте `DEFAULT now()` и `NOT NULL`.
|
||||||
|
- Уникальные ограничения: `uq_<table>__<col>[_<col2>]`.
|
||||||
|
- Первичный ключ: `pk_<table>` (имя создаётся автоматически, но можно переопределить).
|
||||||
|
- Внешние ключи: `fk_<table>__<ref_table>`.
|
||||||
|
- Индексы: `idx_<table>__<col>[_<col2>]`.
|
||||||
|
|
||||||
|
Пример (рекомендуемая версия таблиц):
|
||||||
|
```sql
|
||||||
|
CREATE TABLE contacts (
|
||||||
|
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||||
|
full_name TEXT NOT NULL,
|
||||||
|
email TEXT,
|
||||||
|
department_id BIGINT,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||||
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||||
|
CONSTRAINT uq_contacts__email UNIQUE (email)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE departments (
|
||||||
|
department_id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
CONSTRAINT uq_departments__name UNIQUE (name)
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE contacts
|
||||||
|
ADD CONSTRAINT fk_contacts__departments
|
||||||
|
FOREIGN KEY (department_id)
|
||||||
|
REFERENCES departments(department_id)
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
ON DELETE SET NULL;
|
||||||
|
|
||||||
|
-- Индексы
|
||||||
|
CREATE INDEX idx_contacts__department_id ON contacts(department_id);
|
||||||
|
CREATE INDEX idx_contacts__full_name ON contacts(full_name);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Создание таблицы (с первичным ключом)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE TABLE contacts (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
full_name TEXT NOT NULL,
|
||||||
|
email TEXT UNIQUE,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Операции CRUD
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Создать запись
|
||||||
|
INSERT INTO contacts (full_name, email)
|
||||||
|
VALUES ('Alice Johnson', 'alice@example.com');
|
||||||
|
|
||||||
|
-- Прочитать записи
|
||||||
|
SELECT id, full_name, email, created_at
|
||||||
|
FROM contacts
|
||||||
|
ORDER BY id
|
||||||
|
LIMIT 10;
|
||||||
|
|
||||||
|
-- Обновить запись
|
||||||
|
UPDATE contacts
|
||||||
|
SET email = 'alice@newmail.com'
|
||||||
|
WHERE id = 1;
|
||||||
|
|
||||||
|
-- Удалить запись
|
||||||
|
DELETE FROM contacts
|
||||||
|
WHERE id = 1;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Работа с NULL
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Вставить запись без email (NULL)
|
||||||
|
INSERT INTO contacts (full_name, email) VALUES ('No Email User', NULL);
|
||||||
|
|
||||||
|
-- Найти записи с отсутствующим email
|
||||||
|
SELECT id, full_name, email FROM contacts WHERE email IS NULL;
|
||||||
|
|
||||||
|
-- Найти записи, где email указан
|
||||||
|
SELECT id, full_name, email FROM contacts WHERE email IS NOT NULL;
|
||||||
|
|
||||||
|
-- Подставить значение по умолчанию, если email NULL
|
||||||
|
SELECT id, full_name, COALESCE(email, 'no-email@example.com') AS safe_email
|
||||||
|
FROM contacts;
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Основные команды ALTER TABLE
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Добавить столбец
|
||||||
|
ALTER TABLE contacts ADD COLUMN phone TEXT;
|
||||||
|
|
||||||
|
-- Переименовать столбец
|
||||||
|
ALTER TABLE contacts RENAME COLUMN phone TO phone_number;
|
||||||
|
|
||||||
|
-- Удалить столбец
|
||||||
|
ALTER TABLE contacts DROP COLUMN phone_number;
|
||||||
|
|
||||||
|
-- Изменить тип столбца (пример: TEXT -> VARCHAR)
|
||||||
|
ALTER TABLE contacts ALTER COLUMN full_name TYPE VARCHAR(200);
|
||||||
|
|
||||||
|
-- Добавить первичный ключ в существующую таблицу (если отсутствует)
|
||||||
|
ALTER TABLE contacts ADD COLUMN id SERIAL;
|
||||||
|
ALTER TABLE contacts ADD PRIMARY KEY (id);
|
||||||
|
|
||||||
|
-- Удалить первичный ключ
|
||||||
|
ALTER TABLE contacts DROP CONSTRAINT contacts_pkey;
|
||||||
|
|
||||||
|
-- Переименовать таблицу
|
||||||
|
ALTER TABLE contacts RENAME TO people;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Работа с несколькими таблицами (две)
|
||||||
|
|
||||||
|
Добавим таблицу `departments` и внешний ключ из `contacts` на `departments`.
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Создать таблицу отделов
|
||||||
|
CREATE TABLE departments (
|
||||||
|
department_id SERIAL PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL UNIQUE
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Вернуть имя таблицы people обратно, если переименовывали ранее
|
||||||
|
ALTER TABLE IF EXISTS people RENAME TO contacts;
|
||||||
|
|
||||||
|
-- Добавить внешний ключ на departments
|
||||||
|
ALTER TABLE contacts ADD COLUMN department_id INT;
|
||||||
|
ALTER TABLE contacts
|
||||||
|
ADD CONSTRAINT contacts_department_fk
|
||||||
|
FOREIGN KEY (department_id)
|
||||||
|
REFERENCES departments(department_id)
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
ON DELETE SET NULL;
|
||||||
|
```
|
||||||
|
|
||||||
|
Пример данных:
|
||||||
|
```sql
|
||||||
|
INSERT INTO departments (name) VALUES ('Sales'), ('Engineering'), ('HR');
|
||||||
|
|
||||||
|
UPDATE contacts SET department_id = 1 WHERE id = 1; -- Alice -> Sales
|
||||||
|
-- При необходимости добавьте больше контактов аналогично
|
||||||
|
```
|
||||||
|
|
||||||
|
### Примеры JOIN
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- INNER JOIN: только совпадающие записи
|
||||||
|
SELECT c.id, c.full_name, d.name AS department
|
||||||
|
FROM contacts c
|
||||||
|
JOIN departments d ON d.department_id = c.department_id;
|
||||||
|
|
||||||
|
-- LEFT JOIN: все контакты, даже без отдела
|
||||||
|
SELECT c.id, c.full_name, d.name AS department
|
||||||
|
FROM contacts c
|
||||||
|
LEFT JOIN departments d ON d.department_id = c.department_id;
|
||||||
|
|
||||||
|
-- RIGHT JOIN: все отделы, даже без контактов
|
||||||
|
SELECT c.id, c.full_name, d.name AS department
|
||||||
|
FROM contacts c
|
||||||
|
RIGHT JOIN departments d ON d.department_id = c.department_id;
|
||||||
|
|
||||||
|
-- FULL OUTER JOIN: объединение LEFT и RIGHT
|
||||||
|
SELECT c.id, c.full_name, d.name AS department
|
||||||
|
FROM contacts c
|
||||||
|
FULL JOIN departments d ON d.department_id = c.department_id;
|
||||||
|
```
|
||||||
|
|
||||||
|
### UNION и INTERSECT
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- UNION: объединить результаты (уникальные строки)
|
||||||
|
SELECT full_name AS item FROM contacts
|
||||||
|
UNION
|
||||||
|
SELECT name AS item FROM departments;
|
||||||
|
|
||||||
|
-- INTERSECT: пересечение множеств
|
||||||
|
-- (искусственный пример: найдём такие строки, где имя контакта совпадает с названием отдела)
|
||||||
|
SELECT full_name FROM contacts
|
||||||
|
INTERSECT
|
||||||
|
SELECT name FROM departments;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Оконные функции (window functions) на примере компаний нефти и газа
|
||||||
|
|
||||||
|
Создадим отдельную таблицу `companies` с повторяющимися данными для примеров.
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE TABLE companies (
|
||||||
|
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||||
|
company_name TEXT NOT NULL,
|
||||||
|
sector TEXT NOT NULL, -- 'Oil' | 'Gas'
|
||||||
|
country TEXT NOT NULL, -- страна регистрации
|
||||||
|
revenue_usd NUMERIC(14,2) NOT NULL, -- выручка
|
||||||
|
employees INT NOT NULL, -- число сотрудников
|
||||||
|
founded_year INT, -- год основания (может повторяться)
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO companies (company_name, sector, country, revenue_usd, employees, founded_year) VALUES
|
||||||
|
('PetroOne', 'Oil', 'USA', 1200000.00, 5000, 1980),
|
||||||
|
('GasPrime', 'Gas', 'USA', 800000.00, 3200, 1990),
|
||||||
|
('NordOil', 'Oil', 'Norway',950000.00, 2100, 1975),
|
||||||
|
('EuroGas', 'Gas', 'Norway',400000.00, 1500, 2001),
|
||||||
|
('OilAsia', 'Oil', 'UAE', 2200000.00, 9000, 1970),
|
||||||
|
('GasEast', 'Gas', 'UAE', 1300000.00, 4800, 1988),
|
||||||
|
('LatOil', 'Oil', 'Brazil', 500000.00, 1200, 2005),
|
||||||
|
('SouthGas', 'Gas', 'Brazil', 350000.00, 900, 2005),
|
||||||
|
('OilAsia-2', 'Oil', 'UAE', 1600000.00, 6000, 1970); -- повторяющиеся страна/год/sector
|
||||||
|
```
|
||||||
|
|
||||||
|
Группировки, фильтрация (HAVING), сортировка и LIMIT:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Выручка и среднее число сотрудников по сектору
|
||||||
|
SELECT sector,
|
||||||
|
SUM(revenue_usd) AS total_revenue,
|
||||||
|
AVG(employees)::INT AS avg_employees
|
||||||
|
FROM companies
|
||||||
|
GROUP BY sector
|
||||||
|
HAVING SUM(revenue_usd) > 1000000 -- оставить только сектора с суммарной выручкой > 1 млн
|
||||||
|
ORDER BY total_revenue DESC
|
||||||
|
LIMIT 10;
|
||||||
|
|
||||||
|
-- По стране и сектору
|
||||||
|
SELECT country, sector,
|
||||||
|
COUNT(*) AS num_companies,
|
||||||
|
SUM(revenue_usd) AS total_revenue
|
||||||
|
FROM companies
|
||||||
|
GROUP BY country, sector
|
||||||
|
ORDER BY total_revenue DESC, country;
|
||||||
|
```
|
||||||
|
|
||||||
|
Примеры оконных функций:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Нумерация компаний внутри сектора по выручке (от большей к меньшей)
|
||||||
|
SELECT company_name, sector, revenue_usd,
|
||||||
|
ROW_NUMBER() OVER (PARTITION BY sector ORDER BY revenue_usd DESC) AS rn_in_sector
|
||||||
|
FROM companies
|
||||||
|
ORDER BY sector, rn_in_sector;
|
||||||
|
|
||||||
|
-- Ранги: RANK (с пропусками), DENSE_RANK (без пропусков) внутри сектора
|
||||||
|
SELECT company_name, sector, revenue_usd,
|
||||||
|
RANK() OVER (PARTITION BY sector ORDER BY revenue_usd DESC) AS rnk,
|
||||||
|
DENSE_RANK() OVER (PARTITION BY sector ORDER BY revenue_usd DESC) AS drnk
|
||||||
|
FROM companies
|
||||||
|
ORDER BY sector, rnk;
|
||||||
|
|
||||||
|
-- Сумма и среднее по стране (окно PARTITION BY)
|
||||||
|
SELECT company_name, country, revenue_usd,
|
||||||
|
SUM(revenue_usd) OVER (PARTITION BY country) AS country_revenue_total,
|
||||||
|
AVG(revenue_usd) OVER (PARTITION BY country) AS country_revenue_avg
|
||||||
|
FROM companies
|
||||||
|
ORDER BY country, revenue_usd DESC;
|
||||||
|
|
||||||
|
-- Скользящее среднее по выручке внутри сектора (окно 1 предыдущая, текущая, 1 следующая)
|
||||||
|
SELECT company_name, sector, revenue_usd,
|
||||||
|
AVG(revenue_usd) OVER (
|
||||||
|
PARTITION BY sector
|
||||||
|
ORDER BY revenue_usd
|
||||||
|
ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
|
||||||
|
) AS moving_avg_in_sector
|
||||||
|
FROM companies
|
||||||
|
ORDER BY sector, revenue_usd;
|
||||||
|
|
||||||
|
-- Процентильные ранги и квартиль (NTILE)
|
||||||
|
SELECT company_name, sector, revenue_usd,
|
||||||
|
PERCENT_RANK() OVER (PARTITION BY sector ORDER BY revenue_usd) AS percent_rank_in_sector,
|
||||||
|
CUME_DIST() OVER (PARTITION BY sector ORDER BY revenue_usd) AS cume_dist_in_sector,
|
||||||
|
NTILE(4) OVER (PARTITION BY sector ORDER BY revenue_usd) AS quartile_in_sector
|
||||||
|
FROM companies
|
||||||
|
ORDER BY sector, revenue_usd;
|
||||||
|
|
||||||
|
-- LAG/LEAD: сравнение с соседями по выручке внутри сектора
|
||||||
|
SELECT company_name, sector, revenue_usd,
|
||||||
|
LAG(revenue_usd) OVER (PARTITION BY sector ORDER BY revenue_usd) AS prev_revenue,
|
||||||
|
LEAD(revenue_usd) OVER (PARTITION BY sector ORDER BY revenue_usd) AS next_revenue
|
||||||
|
FROM companies
|
||||||
|
ORDER BY sector, revenue_usd;
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
173
redis.md
Normal file
173
redis.md
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
# Redis в Docker: установка и базовые команды
|
||||||
|
|
||||||
|
Краткая инструкция по запуску Redis в Docker и использованию `redis-cli`.
|
||||||
|
|
||||||
|
## Установка/запуск Redis в Docker
|
||||||
|
|
||||||
|
- Запустить Redis (порт 6379):
|
||||||
|
```bash
|
||||||
|
docker run -d --name redis -p 6379:6379 redis:7
|
||||||
|
```
|
||||||
|
|
||||||
|
- Перезапуск/остановка/удаление:
|
||||||
|
```bash
|
||||||
|
docker restart redis
|
||||||
|
```
|
||||||
|
```bash
|
||||||
|
docker stop redis
|
||||||
|
```
|
||||||
|
```bash
|
||||||
|
docker rm -f redis
|
||||||
|
```
|
||||||
|
|
||||||
|
## Подключение к Redis
|
||||||
|
|
||||||
|
- Из контейнера (встроенный `redis-cli`):
|
||||||
|
```bash
|
||||||
|
docker exec -it redis redis-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
- С хоста (если установлен `redis-cli`):
|
||||||
|
```bash
|
||||||
|
redis-cli -h 127.0.0.1 -p 6379
|
||||||
|
```
|
||||||
|
|
||||||
|
- Проверка доступности:
|
||||||
|
```bash
|
||||||
|
redis-cli -h 127.0.0.1 -p 6379 PING
|
||||||
|
# Ответ: PONG
|
||||||
|
```
|
||||||
|
|
||||||
|
## Базовые команды (ключ-значение)
|
||||||
|
|
||||||
|
```redis
|
||||||
|
# Имена скважин
|
||||||
|
SET well:1001:name "Well-1001"
|
||||||
|
GET well:1001:name
|
||||||
|
|
||||||
|
# Счетчики добычи (баррели нефти)
|
||||||
|
SETNX counters:production:well:1001:bbl 0
|
||||||
|
INCR counters:production:well:1001:bbl
|
||||||
|
INCRBY counters:production:well:1001:bbl 250
|
||||||
|
DECR counters:production:well:1001:bbl
|
||||||
|
|
||||||
|
# Массовая запись/чтение параметров месторождения
|
||||||
|
MSET field:permian:name Permian field:permian:country USA field:permian:type oil
|
||||||
|
MGET field:permian:name field:permian:country field:permian:type
|
||||||
|
|
||||||
|
# Удаление и проверка существования
|
||||||
|
DEL field:permian:type
|
||||||
|
EXISTS well:1001:name
|
||||||
|
TTL counters:production:well:1001:bbl
|
||||||
|
```
|
||||||
|
|
||||||
|
## Время жизни/истечение
|
||||||
|
|
||||||
|
```redis
|
||||||
|
# Кэш телеметрии датчика давления (истекает через 5 минут)
|
||||||
|
SET sensor:well:1001:pressure:psi "2850" EX 300
|
||||||
|
|
||||||
|
# Продлить TTL еще на 60 секунд
|
||||||
|
EXPIRE sensor:well:1001:pressure:psi 60
|
||||||
|
|
||||||
|
# Сделать запись постоянной
|
||||||
|
PERSIST sensor:well:1001:pressure:psi
|
||||||
|
```
|
||||||
|
|
||||||
|
## Поиск ключей и очистка
|
||||||
|
|
||||||
|
```redis
|
||||||
|
KEYS well:*
|
||||||
|
```
|
||||||
|
|
||||||
|
## Структуризация команд
|
||||||
|
|
||||||
|
### 1) Простые типы: строки и числа
|
||||||
|
|
||||||
|
```redis
|
||||||
|
# Строки состояния
|
||||||
|
SET well:1001:status "online"
|
||||||
|
GET well:1001:status
|
||||||
|
|
||||||
|
# Множественная запись паспортных данных скважины
|
||||||
|
MSET well:1001:field Permian well:1001:type oil well:1001:depth_m 3200
|
||||||
|
MGET well:1001:field well:1001:type well:1001:depth_m
|
||||||
|
|
||||||
|
# Только если ключ не существует (инициализация счетчика газа, тыс. куб. футов)
|
||||||
|
SETNX counters:gas:well:1001:mcf 0
|
||||||
|
|
||||||
|
# Инкременты/декременты
|
||||||
|
INCR counters:gas:well:1001:mcf
|
||||||
|
INCRBY counters:gas:well:1001:mcf 500
|
||||||
|
DECR counters:gas:well:1001:mcf
|
||||||
|
|
||||||
|
# Полезное: журнал операций
|
||||||
|
APPEND ops:log "start_pump;"
|
||||||
|
STRLEN ops:log
|
||||||
|
GETSET last:ops:timestamp "2025-10-28T10:00:00Z"
|
||||||
|
DEL ops:log well:1001:status
|
||||||
|
EXISTS counters:gas:well:1001:mcf
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2) Списки (queues/стэки)
|
||||||
|
|
||||||
|
```redis
|
||||||
|
# Очередь работ по обслуживанию
|
||||||
|
LPUSH jobs:maintenance well:1001:inspect well:1002:replace_valve
|
||||||
|
RPUSH jobs:maintenance well:1003:calibrate_sensor
|
||||||
|
|
||||||
|
# Изъятие задач
|
||||||
|
LPOP jobs:maintenance
|
||||||
|
RPOP jobs:maintenance
|
||||||
|
|
||||||
|
# Диапазон и метаданные
|
||||||
|
LRANGE jobs:maintenance 0 -1
|
||||||
|
LLEN jobs:maintenance
|
||||||
|
LINDEX jobs:maintenance 0
|
||||||
|
|
||||||
|
# Блокирующие операции (ожидание новой задачи)
|
||||||
|
BLPOP jobs:maintenance 5
|
||||||
|
BRPOP jobs:maintenance 5
|
||||||
|
|
||||||
|
# Удаление конкретной задачи
|
||||||
|
LREM jobs:maintenance 0 well:1002:replace_valve
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3) Хэши (похожие на объекты)
|
||||||
|
|
||||||
|
```redis
|
||||||
|
# Паспорт скважины
|
||||||
|
HSET well:1001 name "Well-1001" field "Permian" status "online" depth_m 3200
|
||||||
|
HGET well:1001 name
|
||||||
|
HMGET well:1001 field status depth_m
|
||||||
|
HGETALL well:1001
|
||||||
|
|
||||||
|
# Управление полями
|
||||||
|
HDEL well:1001 status
|
||||||
|
HEXISTS well:1001 field
|
||||||
|
HLEN well:1001
|
||||||
|
|
||||||
|
# Счетчики в хэше (например, количество запусков насоса)
|
||||||
|
HINCRBY well:1001 metrics:pump_starts 1
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4) Множества (уникальные элементы, без порядка)
|
||||||
|
|
||||||
|
```redis
|
||||||
|
# Скважины по месторождениям
|
||||||
|
SADD field:permian:wells 1001 1002
|
||||||
|
SADD field:west_siberia:wells 1002 1003
|
||||||
|
SMEMBERS field:permian:wells
|
||||||
|
SCARD field:west_siberia:wells
|
||||||
|
|
||||||
|
# Операции множеств (пересечения/объединения между полями)
|
||||||
|
SUNION field:permian:wells field:west_siberia:wells # 1001 1002 1003
|
||||||
|
SINTER field:permian:wells field:west_siberia:wells # 1002
|
||||||
|
SDIFF field:permian:wells field:west_siberia:wells # 1001
|
||||||
|
|
||||||
|
# Теги оборудования на скважине
|
||||||
|
SADD well:1001:tags oil onshore artificial_lift
|
||||||
|
SISMEMBER well:1001:tags oil
|
||||||
|
```
|
||||||
|
|
||||||
|
> Примечание: отсортированные множества (ZSET) и другие структуры (Streams, Bitmaps, HyperLogLog) можно добавить позже по мере необходимости.
|
||||||
Loading…
Reference in New Issue
Block a user