Add initial documentation for MongoDB, Neo4j, pgAdmin, PostgreSQL, and Redis in Docker

This commit is contained in:
Denis Volkov 2025-10-28 15:59:56 +03:00
commit 699dd0d18f
6 changed files with 792 additions and 0 deletions

93
README.md Normal file
View 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
View 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
View 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
View 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
View 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
View 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) можно добавить позже по мере необходимости.