Files
Baradb/docs/ru/baraql.md
T

12 KiB
Raw Blame History

Справочник по языку запросов BaraQL

BaraQL — это совместимый с SQL язык запросов с расширениями для графовых, векторных и документных операций.

Типы данных

Тип Описание Пример
null Null значение null
bool Булевый true, false
int8 8-битное знаковое целое 127
int16 16-битное знаковое целое 32767
int32 32-битное знаковое целое 2147483647
int64 64-битное знаковое целое 9223372036854775807
float32 32-битное с плавающей точкой 3.14
float64 64-битное с плавающей точкой 3.14159265359
str UTF-8 строка 'hello'
bytes Сырые байты 0xDEADBEEF
array<T> Однородный массив [1, 2, 3]
vector Вектор float32 [0.1, 0.2, 0.3]
object Объект ключ-значение {"a": 1}
datetime timestamp ISO 8601 '2025-01-15T10:30:00Z'
uuid UUID v4 '550e8400-e29b-41d4-a716-446655440000'
json JSON документ {"key": "value"}
jsonb Бинарный JSON (проверенный) {"key": "value"}

Базовые запросы

SELECT

-- Все столбцы
SELECT * FROM users;

-- Конкретные столбцы
SELECT name, age FROM users;

-- Псевдонимы
SELECT name AS full_name, age AS years FROM users;

-- DISTINCT
SELECT DISTINCT department FROM employees;

-- LIMIT и OFFSET
SELECT * FROM users LIMIT 10 OFFSET 20;

WHERE

-- Операторы сравнения
SELECT * FROM users WHERE age > 18;
SELECT * FROM users WHERE age >= 18 AND age <= 65;
SELECT * FROM users WHERE name = 'Alice';
SELECT * FROM users WHERE name != 'Bob';

-- Диапазон
SELECT * FROM users WHERE age BETWEEN 18 AND 65;

-- Проверка принадлежности
SELECT * FROM users WHERE department IN ('Engineering', 'Sales');

-- Поиск по шаблону
SELECT * FROM users WHERE name LIKE 'A%';
SELECT * FROM users WHERE name ILIKE 'alice';  -- Без учёта регистра

-- Проверка на NULL
SELECT * FROM users WHERE email IS NOT NULL;

-- Логические операторы
SELECT * FROM users WHERE age > 18 AND (department = 'Engineering' OR department = 'Sales');

ORDER BY

-- По возрастанию (по умолчанию)
SELECT * FROM users ORDER BY age;

-- По убыванию
SELECT * FROM users ORDER BY age DESC;

-- Несколько столбцов
SELECT * FROM users ORDER BY department ASC, age DESC;

INSERT

-- Одна строка
INSERT users { name := 'Alice', age := 30 };

-- С явным типом
INSERT User { name := 'Alice', age := 30 };

-- Несколько строк
INSERT users {
  { name := 'Alice', age := 30 },
  { name := 'Bob', age := 25 }
};

UPDATE

-- Обновить все строки
UPDATE users SET status = 'active';

-- Условное обновление
UPDATE users SET age = 31 WHERE name = 'Alice';

-- Обновить несколько столбцов
UPDATE users SET age = 32, status = 'premium' WHERE name = 'Alice';

DELETE

-- Удалить все строки
DELETE FROM users;

-- Условное удаление
DELETE FROM users WHERE age < 18;

Агрегация и группировка

Агрегатные функции

Функция Описание
count(*) Подсчёт всех строк
count(column) Подсчёт не-NULL значений
sum(column) Сумма значений
avg(column) Среднее значение
min(column) Минимальное значение
max(column) Максимальное значение
stddev(column) Стандартное отклонение
variance(column) Дисперсия

GROUP BY

SELECT department, count(*) as emp_count, avg(salary) as avg_salary
FROM employees
GROUP BY department;

-- С HAVING
SELECT department, count(*) as emp_count
FROM employees
GROUP BY department
HAVING count(*) > 5;

-- Несколько группировок
SELECT department, role, count(*), avg(salary)
FROM employees
GROUP BY department, role;

JOIN

-- INNER JOIN
SELECT u.name, o.total
FROM users u
INNER JOIN orders o ON u.id = o.user_id;

-- LEFT JOIN
SELECT u.name, o.total
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;

-- RIGHT JOIN
SELECT u.name, o.total
FROM users u
RIGHT JOIN orders o ON u.id = o.user_id;

-- FULL JOIN
SELECT u.name, o.total
FROM users u
FULL JOIN orders o ON u.id = o.user_id;

-- CROSS JOIN
SELECT u.name, p.name
FROM users u
CROSS JOIN products p;

-- Несколько JOIN
SELECT u.name, o.id, p.name
FROM orders o
JOIN users u ON o.user_id = u.id
JOIN products p ON o.product_id = p.id;

-- Self JOIN
SELECT e.name, m.name as manager
FROM employees e
JOIN employees m ON e.manager_id = m.id;

CTE (Common Table Expressions)

-- Один CTE
WITH active_users AS (
  SELECT * FROM users WHERE active = true
)
SELECT * FROM active_users;

-- Несколько CTE
WITH
  recent AS (
    SELECT * FROM orders WHERE date > '2025-01-01'
  ),
  totals AS (
    SELECT user_id, sum(amount) as total FROM recent GROUP BY user_id
  )
SELECT u.name, t.total
FROM users u
JOIN totals t ON u.id = t.user_id;

-- Рекурсивный CTE
WITH RECURSIVE subordinates AS (
  SELECT id, name, manager_id FROM employees WHERE name = 'CEO'
  UNION ALL
  SELECT e.id, e.name, e.manager_id
  FROM employees e
  JOIN subordinates s ON e.manager_id = s.id
)
SELECT * FROM subordinates;

Подзапросы

-- Подзапрос в SELECT
SELECT name, (SELECT count(*) FROM orders WHERE user_id = u.id) as order_count
FROM users u;

-- Подзапрос в FROM
SELECT * FROM (SELECT id, name FROM users WHERE active = true) AS active;

-- Подзапрос в WHERE (IN)
SELECT name FROM users WHERE id IN (SELECT user_id FROM orders);

-- Подзапрос в WHERE (EXISTS)
SELECT name FROM users WHERE EXISTS (SELECT 1 FROM orders WHERE orders.user_id = users.id);

-- Коррелированный подзапрос
SELECT name FROM users u
WHERE age > (SELECT avg(age) FROM users WHERE department = u.department);

CASE выражения

SELECT name,
  CASE
    WHEN age < 13 THEN 'child'
    WHEN age < 20 THEN 'teenager'
    WHEN age < 65 THEN 'adult'
    ELSE 'senior'
  END AS category
FROM users;

-- Простой CASE
SELECT name,
  CASE department
    WHEN 'Engineering' THEN 'Tech'
    WHEN 'Sales' THEN 'Revenue'
    ELSE 'Other'
  END AS division
FROM employees;

Операции над множествами

-- UNION (уникальные)
SELECT name FROM customers
UNION
SELECT name FROM suppliers;

-- UNION ALL (с дубликатами)
SELECT name FROM customers
UNION ALL
SELECT name FROM suppliers;

-- INTERSECT
SELECT name FROM customers
INTERSECT
SELECT name FROM suppliers;

-- EXCEPT
SELECT name FROM customers
EXCEPT
SELECT name FROM suppliers;

Определение схемы

CREATE TYPE

CREATE TYPE Person {
  name: str,
  age: int32
};

-- С обязательными полями
CREATE TYPE User {
  email: str REQUIRED,
  name: str,
  age: int32,
  created_at: datetime DEFAULT now()
};

-- Со связями
CREATE TYPE Movie {
  title: str,
  year: int32,
  director: Person
};

-- С вычисляемыми свойствами
CREATE TYPE Employee {
  name: str,
  base_salary: float64,
  bonus: float64,
  total_compensation: float64 COMPUTED (base_salary + bonus)
};

Наследование

CREATE TYPE Animal {
  name: str
};

CREATE TYPE Dog EXTENDING Animal {
  breed: str
};

CREATE TYPE Cat EXTENDING Animal {
  indoor: bool
};

Индексы

CREATE INDEX idx_users_name ON users(name);
CREATE UNIQUE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_age ON users(age) USING btree;

DROP

DROP TYPE User;
DROP INDEX idx_users_name;

Векторный поиск

-- Вставка с вектором
INSERT articles {
  title := 'Nim Programming',
  embedding := [0.1, 0.2, 0.3, 0.4]
};

-- Поиск по сходству (косинусное расстояние)
SELECT title FROM articles
ORDER BY cosine_distance(embedding, [0.1, 0.2, 0.3, 0.4])
LIMIT 5;

-- Евклидово расстояние
SELECT title FROM articles
ORDER BY l2_distance(embedding, [0.1, 0.2, 0.3, 0.4])
LIMIT 5;

-- Скалярное произведение
SELECT title FROM articles
ORDER BY dot_product(embedding, [0.1, 0.2, 0.3, 0.4]) DESC
LIMIT 5;

-- С фильтрацией по метаданным
SELECT title FROM articles
WHERE category = 'tech'
ORDER BY cosine_distance(embedding, [0.1, 0.2, 0.3, 0.4])
LIMIT 5;

Графовые шаблоны

-- Найти друзей Alice
MATCH (p:Person)-[:KNOWS]->(friend:Person)
WHERE p.name = 'Alice'
RETURN friend.name;

-- Найти кратчайший путь
MATCH path = shortestPath((a:Person)-[:KNOWS*1..5]->(b:Person))
WHERE a.name = 'Alice' AND b.name = 'Bob'
RETURN path;

-- Найти все связи
MATCH (p:Person)-[r]->(other)
WHERE p.name = 'Alice'
RETURN type(r), other.name;

-- Несколько прыжков
MATCH (a:Person)-[:KNOWS]->(b:Person)-[:KNOWS]->(c:Person)
WHERE a.name = 'Alice'
RETURN c.name;

-- С агрегатами
MATCH (p:Person)-[:KNOWS]->(friend)
RETURN p.name, count(friend) as friend_count
ORDER BY friend_count DESC;

Полнотекстовый поиск

-- Базовый поиск
SELECT * FROM articles
WHERE MATCH(title, body) AGAINST('database programming');

-- С оценкой релевантности
SELECT title, relevance()
FROM articles
WHERE MATCH(title, body) AGAINST('Nim language')
ORDER BY relevance() DESC;

-- Булев режим
SELECT * FROM articles
WHERE MATCH(title, body) AGAINST('+Nim -Python' IN BOOLEAN MODE);

-- Нечёткий поиск
SELECT * FROM articles
WHERE MATCH(title) AGAINST('programing' WITH FUZZINESS 2);

Транзакции

BEGIN;
INSERT users { name := 'Alice', age := 30 };
INSERT orders { user_id := last_insert_id(), total := 100 };
COMMIT;

-- С точкой сохранения
BEGIN;
INSERT users { name := 'Bob', age := 25 };
SAVEPOINT sp1;
INSERT orders { user_id := last_insert_id(), total := 200 };
-- Ой, откатываемся к точке сохранения
ROLLBACK TO sp1;
COMMIT;

Пользовательские функции

-- Зарегистрировать UDF
CREATE FUNCTION greet(name str) -> str {
  RETURN 'Hello, ' || name || '!';
};

-- Использовать
SELECT greet(name) FROM users;

-- Встроенные функции
SELECT abs(-5), sqrt(16), lower('HELLO'), len('test');

Подсказки запросов

-- Принудительно использовать индекс
SELECT /*+ USE_INDEX(idx_users_age) */ * FROM users WHERE age > 18;

-- Принудительно приближённый векторный поиск
SELECT /*+ APPROXIMATE */ * FROM vectors
ORDER BY cosine_distance(embedding, [...])
LIMIT 10;

-- Параллельное выполнение
SELECT /*+ PARALLEL(4) */ * FROM large_table;