https://qiita.com/iisaka51/items/45f23df873ea5be433c7
@iisaka51 (Гоичи (Иисака) Юкава)
Rust
База данных
RocksDB
TiKV
surrealdb
Последнее обновление 15 мая 2023 г.
Опубликовано 21 января 2023 г.
Введение.
В данном документе приводится краткое описание SurrealDB, опубликованное в июле 2022 года.
История SurrealDB
Она находится в разработке с 2016 года, хотя публично доступна лишь короткое время
Февраль 2016 Разработка началась на языке GoLang
2017 Jul Начата эксплуатация в качестве SaaS back-end БД
2021 окт Принято решение о выпуске с открытым исходным кодом, перестроена на Rust
2022 июл Выпущена бета-версия.1
2022 авг Выпущена Beta.5
2022 окт Выпущена Beta.8
SurrealDB Inc.
Ноябрь 2021 Создана компания SurrealDB Ltd. в Лондоне
Январь 2023 г. Привлечено 6 млн долл. для создания DBaaS
История создания SurrealDB
Основные тенденции
Абстрагирование от баз данных, облака, бессерверные технологии
Все больше компаний переходят на DBaaS
61% разработчиков/операторов завершили или собираются завершить полный > переход на DBaaS, согласно опросу, проведенному компанией MariaDB
Растущий объем рынка DBaaS
До 24,8 млрд. долл. к 2025 году
Богатый инвестиционный климат для DBaaS
SingleStore привлекает 30 млн долларов (2022/окт)
EdgeDB привлекает $15 млн (2022/ноябрь)
SurrealDB привлекает $6 млн (январь 2023 г.)
Профиль SurrealDB
Новости Hacke's Top page
№ 4 2022/авг
№ 2 2022/сентябрь
Занимает первое место в рейтинге GitHub Featured Repositories
2022/авг
2022/дек
Звезда GitHub
От 180 звезд до 1500 звезд за 48 часов
5000 звезд за 3 недели после публикации
10 000 звезд в течение 4 недель после публикации
№1 в "Горячем списке" Reddit по разделам "Программирование" и "Rust
Лицензия SurrealDB
Исходный код SurrealDB лицензируется на условиях Business Software License 1.1.
SDK и библиотеки/драйверы находятся под лицензией MIT
SurrealDB BSL позволяет использовать SurrealDB на неограниченном количестве узлов при условии, что вы не предлагаете ее в качестве коммерческой DBaaS.
Может быть встроена в продукты
SurrealDB BSL действует в течение 4 лет
1 января 2026 года это ограничение истекает, и код становится открытым исходным кодом в соответствии с действующей лицензией Apache License 2.0
Свободное использование для любых целей
Особенности SurrealDB
Реализована на языке Rust
Устойчивость к сегментационным ошибкам
Кросс-компиляция
Относительно быстрый по сравнению с другими языками
Небольшой вес: размер двоичного файла для Linux - 24 МБ, для macOS - 44 МБ
Сервер и REPL-клиент в одном бинарном файле
Простая установка
Поддержка HTTP/Restful API
Поддержка WebSockets
Внутренние БД: EchoDB, RocksDB, TiKV, FoundationDB, IndexedDB
Особенности как базы данных
Бессхемность: нет необходимости определять схему
Различные форматы хранения данных: таблицы, документы, графы и т.д.
Многорядные, многотабличные ACID-транзакции
Связи по рекордным ссылкам и направленным графам
Не требуется JOIN, разумное избежание проблемы N+1
Предопределенные аналитические запросы
Выборка, агрегирование, группировка и упорядочивание данных по мере их написания
Возможность расширения запросов с помощью встроенного JavaScript
Возможность записи регулярных выражений в запросах (/regex/)
Поддержка GeoJSON
Возможность параллельного выполнения операций CRUD
Сильные стороны SurrealDB
Дифференцирующие функции в то же время
Пользователи могут обращаться к ней непосредственно из фронтенда
База данных может быть должным образом сконфигурирована для аутентификации и авторизации
Синхронизация данных в реальном времени
Мало конкурентов, например Google Firestore
Единственная в своем роде БД при локальном использовании
Аутентификация и авторизация на стороне базы данных...
Может обеспечивать контроль доступа на основе ролей
Контроль доступа на основе заданных ролей, таких как администратор, редактор, зритель и т.д.
Слабые стороны SurrealDB
Пока не опубликована (июль 2022 г.).
Возможны потенциальные уязвимости и ошибки в системе безопасности
PostgreSQL впервые опубликован в 1997 году, предшественник Postgress - в 1989 году)
Первая версия MySQL была опубликована в 1995 году
MariaDB впервые опубликована в 2009 году
MongoDB впервые опубликована в 2009 году
Мало информации.
Официальная документация находится в процессе производства
Если есть сомнения, читайте исходный код
Не все возможности реализованы
SurrealDB в настоящее время не приносит прибыли: сервис DBaaS будет доступен в 2023 году
Возможности, находящиеся в стадии разработки (в beta.9 еще не реализованы)
Поддержка нескольких узлов в распределенном режиме
Репликация
Проверка работоспособности
GraphQL
FULLTEXT - полнотекстовое индексирование
Поля LEARN
Автоматическая настройка на основе анализа заданных полей методом машинного обучения
Версионные временные таблицы
Возможность "возврата в прошлое" при обращении к данным
Подсветка кода в IDE (Atom, VSCode, Vim...)
Выпуск приложения для работы с пользовательскими интерфейсами планируется в версии 1.x
Обзор двухуровневой архитектуры SurrealDB
surrealdb_arch.png
Обзор работы SurrealDB
surrealdb_dataflow.png
Исходный код.
Цифрами обозначено количество строк, включая комментарии (SurrealDB 1.0.0-beta.8).
Кстати, MariaDB 10.9 имеет более 1,3 млн строк (только для клиента - более 12 тыс. строк).
|-- src // Уровень API 4172
|-- net 1981
|-- cli 895
|-- rpc 174
...
|-- lib/src // BL Layer 32261
|-- sql 19030
|-- fnc 3524
...
|-- kvs 3286
|-- indexdb 220
|-- rocksdb 316
|-- tikv 269
...
В SurrealDB реализовано на удивление мало функций
Для разбора запросов используются функции nom
Функции могут быть соединены в цепочку для инкрементного построения парсеров
Использование echodb для хранения данных в памяти (Тоби)
In-Memory KVS DB с многоверсионным контролем параллелизма
Использование storekey для хранения в KVS (Tobie)
Двоичное кодирование с сохранением порядка в словаре
Полезно для создания отсортированных ключей KVS
Использование MsgPack и serde для сериализации/десериализации (rmp-serde)
Использование geo для парсинга GeoJSON
Использование RocksDB для использования локальных файлов в качестве хранилища данных
Использование TiKV и FoundationDB для функциональности распределенной БД
Элементы, которые SurrealDB хранит в KVS
Метаданные
Таблицы, индексы, диапазоны и другие структуры
Данные.
Значения объектов, хранящихся в SurrealDB
Как SurrealDB хранит данные в KVS
Структуры Map Rust и MsgPack с привязками serde
Экономия объема хранилища
Эффективность сериализации/десериализации
Два метода доступа к данным в KVS
По ключу: указываем конкретный ключ и получаем значение (быстро)
Сканирование: указать диапазон ключей и получить все значения (медленно)
Иерархическая структура сохраняется в ключах
Пространство имен -> База данных -> Таблица -> ID
SurrealDB преобразует иерархическую структуру ключей в диапазоны для сканирования
Установка (простая и быстрая)
Linux.
$ curl -sSf https://install.surrealdb.com | sh
macOS
$ brew install surrealdb/tap/surreal
Windows.
PS C:\> iwr https://windows.surrealdb.com -useb | iex
Docker/Podmandocker
$ docker run --rm -p 8000:8000 surrealdb/surrealdb:latest start
$ podman run --rm -p 8000:8000 surrealdb/surrealdb:latest start
Запуск SurrealDB
Первым аргументом подкоманды start является место назначения, куда будут записываться данные.
По умолчанию это память
$ surreal start --user root --pass root memory
Другие направления экспорта
file:///path/to/data.db файловая система (RocksDB)
rocksdb:///path/to/data.db RocksDB
tikv://endpoiint TiKV TiKV
fdb:[///path/to/clusterfile] FoundationDB (требуется пересборка)
Режим STRICT.
--strict Начните с указания опций.
NAMESPACE,, DATABASE должны быть определены, иначе возникнет ошибка
Ошибка, если не определена таблица TABLE
Сброс/восстановление
Выгрузка в файл с помощью подкоманды export
Восстановление из файла с помощью подкоманды import
$ surreal export --conn http://dev00:8000 --ns test --db test dump.db
$ surreal import --conn http://dev00:8000 --ns test --db test dump.db
Подключение из клиента CLI
Выполните подкоманду sql
$ surreal sql --conn http://dev00:8000 --ns test --db test --pretty
--user и --pass ROOT аутентификация пользователь/пароль
--pretty для форматирования и отображения вывода в формате JSON
--ns NAMESPACE --db instruct DATABASE
Когда SurrealDB работает в режиме STRICT, опции -ns и -db игнорируются.
HTTP RESTful API
PATH TYPE Описание.
/key/:table GET Получить все записи в таблице из базы данных.
/key/:table/:id GET Получить конкретную запись из базы данных.
/key/:table POST Создать запись в таблице в базе данных
/key/:table/:id POST Создать конкретную запись в таблице в базе данных
/key/:table/:table DELETE Удалить все записи таблицы из базы данных
/key/:table/:id PUT Обновление указанной записи в базе данных
/key/:table/:id PATCH Модифицирует указанную запись в базе данных
/key/:table/:id DELETE Удаляет указанную запись из базы данных.
HTTP RESTful API (продолжение)
PATH TYPE Описание.
/version GET Возвращает версию SurrealDB
/signup POST Регистрация для аутентификации SCOPE
/signin POST Вход в систему с аутентификацией SCOPE
/rpc POST Запрос к WebSocket с помощью JON-RPC
/sql POST Разрешить запросы на языке SurQL
/export GET Выгрузить содержимое базы данных
/import POST Применить содержимое запроса к базе данных (восстановить)
HTTP RESTful API (неполный)
PATH TYPE Описание.
/sync GET Репликация
/health GET Проверка состояния базы данных
/status GET Возврат статуса
Определения таблиц в общем виде SQL
CREATE TABLE human (
id int, nickname text, прозвище
текст прозвища,
возраст int,
PRIMARY KEY(id)
);
SurealDB не имеет схемы
Нет необходимости определять таблицы и поля
Нет необходимости вносить изменения при добавлении полей
Если сервер запускается в режиме STRICT, то сначала требуется определить таблицы
CREATE human:freddie SET nickname="freddie", age=99 ;
CREATE human:brian SET nickname="brian", age=75, sex=true ;
ID == TableName:UniqID Обратите внимание, что ID содержит имя таблицы.
Указание типа поля без схемы
CREATE human:freddie SET
nickname = <string> "freddie",.
age = <int> 99 ;
Типы и приведения
bool, int, float, string, number, decimal, datetime, duration
Строки даты/времени преобразуются в формат ISO 8601: то же самое, что и приведение в <datetime>.
Если вы хотите рассматривать строку datetime как строку, как она есть, выполните приведение с помощью <string>.
SELECT * FROM "2023-01-01";.
SELECT * FROM <datetime> "2023-01-01";
SELECT * FROM <string> "2023-01-01T02:03:00Z" + "-test";
Определение схемы
DEFINE TABLE human SCHEMAFULL;
DEFINE FIELD nickname ON human TYPE string;
DEFINE FIELD age ON human TYPE int;
[re]определить таблицу как SCHMALESS
DEFINE TABLE human SCHEMALESS ;
DEFINE TABLE human SCHMAFULL; [re]define table as SCHMAFULL
DEFINE TABLE human SCHEMAFULL ;
SCHEMAFULL
Хранятся только данные, допустимые в определенных полях.
Может быть ограничено определенными типами данных
DEFINE FIELD может устанавливать значение по умолчанию, если данные не введены.
Устанавливаемое значение задается в $value
DEFINE TABLE person SCHEMAFULL;.
DEFINE FIELD name ON person TYPE string VALUE $value OR 'guest';.
Добавление данных
Если поле -id опущено, то идентификатор устанавливается автоматически
INSERT INTO human (nickname, age)
VALUES ('brian', 75);
INSERT INTO human (id, nickname, age)
VALUES ('human:freddie', 'freddie', -1);
CREATE human:robert SET nickname='robert', age=30;
CREATE human SET
id = human:jack, nickname='jack', age=30;
CREATE human CONTENT
{ id: 'human:john', nickname: 'john', age: 99 };
INSERT
При наличии дублирующихся идентификаторов можно выполнить UPDATE
INSERT INTO test (id, test, something)
VALUES ('tester', true, 'other');
INSERT INTO test (id, test, something)
VALLUES ('tester', true, 'other' )
ON DUPLICATE KEY UPDATE something = 'else' ;
Вложенные поля
Поля в таблице могут быть вложенными.
Ссылки на вложенные поля могут быть сделаны с помощью точечных обозначений
UPDATE person:test CONTENT {
параметры: {
вложенные: {
объект: {
вещь: 'test'
}
}
}
};
SELECT settings.nested.object FROM person ;.
NONE и NULL
Поле может иметь значения NONE и NULL
NONE: значение не задается
NULL: задается пустое значение
CREATE person:test1 SET email = 'info@example.com';
CREATE person:test2 SET email = NONE;
CREATE person:test3 SET email = NULL;
USE.
Укажите NAMESPACE и DATABASE, которые будут использоваться.
Действует при доступе с аутентификацией ROOT.
USE NAMESPACE test ;
USE NAMESPACE test DATABASE db1 ;
USE NS test test DB db1 ;
Отношение в общем случае SQL
CREATE TABLE armor (
id int,
имя текст,
сопротивление текст,
PRIMARY KEY(id)
);
INSERT INTO armor VALUES
(0, "кожа", 3);
(1, "platemail", 30),
(2, "chainmail", 20),.
CREATE TABLE player (
имя текст,
сила int,
armor_id int,
PRIMARY KEY((name),.
CONSTRAIN fk_armor
FOREIGN KEY(armor_id)
REFERENCECS armor(id)
);
Отношение в SurrealQL (SurQL)
CREATE armor:leather SET registance = 3;
CREATE armor:chainmail SET registance = 20;
CREATE armor:platemail SET registance = 30;
CREATE player:jack SET strength = 22, armor = armor:platemail;
CREATE player:brian SET strength = 20, armor = armor:leather;
Использование имен таблиц в идентификаторах
SurQL: Отношение с определенной схемой
DEFINE TABLE armor SCHEMAFULL;.
DEFINE FIELD resistance ON armor TYPE int;.
CREATE armor:leather SET resistance = 3;
CREATE armor:chainmail SET resistance = 20;
CREATE armor:platemail SET resistance = 30;
DEFINE TABLE player SCHEMAFULL;.
DEFINE FIELD strength ON player TYPE int;
DEFINE FIELD armor ON player TYPE record(armor);
CREATE player:jack SET strength = 22, armor = armor:platemail;
CREATE player:brian SET strength = 20, armor = armor:leather;
Общие отношения SQL: JOIN
SELECT
player.name,
player.strength,.
armor.name AS armor_name,.
armor.resistance AS armor_resistance
FROM игрок
JOIN armor
ON armor.id = player.armor_id
Отношение на языке SurQL: JOIN не требуется
FETCH расширяет указанное поле
SELECT * FROM player FETCH armor;.
Ссылка на запись
CREATE armor:leather SET registance = 3;
CREATE armor:chainmail SET registance = 20;
CREATE armor:platemail SET registance = 30;
CREATE player:jack SET strength = 22, armor = armor:platemail;
CREATE player:brian SET strength = 20, armor = armor:leather;
Внешний ключ == Ссылка на запись
Отношение: один к одному
CREATE human:freddie SET nickname="freddie", age=99 ;
CREATE human:brian SET nickname="brian", age=75
UPDATE human:brian SET bff = human:freddie;
SELECT bff.nickname, bff.age FROM human:brian
Укажите поля во внешней таблице, соединив их точками
Отношение: один-ко-многим
CREATE car:tesla SET model='Model S', ev=True, price=99000;
CREATE car:mustang SET model='Mustang Cobra', ev=False, price=60000;
UPDATE human:brian SET cars=["car:tesla"];
UPDATE human:freddie SET cars=["car:mustang"];
UPDATE car:tesla SET owner = human:brian;
UPDATE car:mustang SET owner = human:freddie;
CREATE parts:tire SET brand='Michelin', size=5;
CREATE parts:gastank SET brand='Tanksy', size=10;
CREATE parts:battery SET brand='Xi Ping', size=20;
UPDATE car:mustang SET parts = ['parts:tire', 'parts:gastank'];
UPDATE car:tesla SET parts = ['parts:tire', 'parts:battery'];
ОТНОШЕНИЕ: ОДИН-КО-МНОГИМ
SELECT parts FROM car:mustang
SELECT cars.parts.brand FROM human:brian ;.
Указывать поля во внешних таблицах, соединяя их точками
Графические связи
RELATE player:jack -> wants_to_buy -> armor:dragon;
RELATE player:jack -> wants_to_buy -> armor:platemail;
SELECT * FROM wants_to_buy;
SELECT id, -> wants_to_buy -> armor AS wtb FROM player;
SELECT id, <- wants_to_buy <- player AS players FROM armor:dragon
Указывайте поля во внешних таблицах, соединяя их символами "->" или "<-".
LIMIT.
Определяет количество результатов, возвращаемых командой SELECT.
В настоящее время прямое управление FETCH работает плохо
CREATE tag:rs SET name = 'Rust';.
CREATE tag:go SET name = 'Golang';
CREATE tag:js SET name = 'JavaScript';
CREATE person:tobie SET tags = [tag:rs, tag:go, tag:js];
CREATE person:jaime SET tags = [tag:js];
SELECT * FROM person LIMIT 1;
SELECT * FROM (SELECT * FROM person FETCH tags) LIMIT 1;
// SELECT * FROM person LIMIT 1 FETCH tags;
START.
Задает начальную позицию результата, возвращаемого SELECT (с нулевым базисом).
Хорошо работает, когда указывается FETCH
SELECT * FROM person START AT 1;
SELECT * FROM (SELECT * FROM person FETCH tags) START 1;
SELECT * FROM person START 1 FETCH tags;
SurQL: WHERE, ORDER BY, GROUP BY
SELECT * FROM armor ;
SELECT * armor WHERE resistance >= 30 ;
SELECT math::sum(strength) FROM player GROUP BY ALL ;
SELECT * FROM armor ORDER BY RAND();
SELECT * FROM armor ORDER RAND();
SELECT * FROM armor ORDER resistance NUMERIC ASC ;
SELECT * FROM armor ORDER resistance NUMERIC DESC ;
SurQL: BEFORE, AFTER, DIFF
CREATE, UPDATE и DELETE могут возвращать данные до, после и разность запросов
UPDATE human:freddie SET email = 'freddie@example.com';
UPDATE human:freddie SET email = 'freddie@dummy.com' RETURN DIFF ;.
Предварительное определение аналитических запросов
После записи данных выполните отбор, агрегирование, группировку, упорядочивание и т.д.
DEFINE TABLE person SCHEMALESS;.
DEFINE TABLE person_by_age AS
SELECT
count(),.
возраст,.
math::sum(age) AS total, math::mean(age) AS average
math::mean(age) AS average
FROM person
GROUP BY age ;
СОБЫТИЕ.
Содержимое таблицы, заданной параметром ON TABLE: $before, $after
ID, по которому произошло событие: $this
Событие, которое произошло: $event
UPDATE human:freddie SET email = 'freddie@example.com';
UPDATE human:brian SET email = 'brian@example.com';
DEFINE EVENT changelog ON TABLE human
WHEN $before.email ! = $after.email
THEN ( CREATE changelog SET
time = time::now(),.
email = $after.email );
RANGE Повторять столько раз, сколько указано двоеточием
> CREATE |test:10| SET time = time::now()
[
{
"result": [
{
"id": "test:g9hq0dowz77us5yvxnst",.
"time": "2022-12-20T04:10:19.282031670Z"
},
{
"id": "test:nk45tn46dy2bn1hd6zj9", { "time".
"time": "2022-12-20T04:10:19.282450969Z"
},.
RANGE Повторить с указанием начального и конечного значений.
> CREATE |test:1..10| SET time = time::now()
[
{
"result": [
{
"id": "test:1",.
"time": "2022-12-20T04:12:21.477667592Z"
},
{
"id": "test:2", "time".
"time": "2022-12-20T04:12:21.478289880Z"
},.
Регулярное выражение.
> SELECT * FROM test WHERE id = /. *[24]. */
[
{
"result": [
{
"id": "test:2",.
"time": "2022-12-20T04:12:21.478289880Z"
},
{
"id": "test:4", "time".
"time": "2022-12-20T04:12:21.478332436Z"
}
],.
"status": "OK",.
IF THEN ELSE
UPDATE person SET classtype =
IF age <= 10 THEN
'junior'.
ELSE IF age <= 21 THEN
'студент'
ELSE IF age >= 65 THEN
'старший'
ELSE
NULL
END ;
MERGE.
Слияние полей таблицы: добавление, удаление
UPDATE person:test SET
name.initials = 'TMH',.
name.first = 'Tobie',.
name.last = 'Morgan Hitchcock';.
UPDATE person:test MERGE {
имя: {
title: 'Mr',.
инициалы: NONE,.
суффикс: ['BSc', 'MSc'], }
}
};
Ограничения таблицы ASSERT
Каждое определяемое поле может задавать ограничения на данные в ASSERT
DEFINE FIELD countrycode ON user TYPE string
// Убедитесь, что код страны соответствует стандарту ISO-3166
ASSERT $value ! = NONE AND $value = /[A-Z]{3}/
// Установить значение по умолчанию, если пусто
VALUE $value OR 'GBR'
;.
Функция FUTURE
- Определение полей таблицы по значениям, которые будут заданы позже
UPDATE person:test SET
can_drive = <future> {
день рождения && time::now() > день рождения + 18y };
UPDATE person:test SET birthday = <datetime> '2007-06-22';
UPDATE person:test SET birthday = <datetime> '2001-06-22';
ПЕРМИССИИ.
Ограничение CRUD-операций над TABLE и FIELD
DEFINE TABLE user SCHEMALESS
PERMISSIONS
Для операций select, create, update
WHERE id = $auth.id
для удаления
WHERE id = $auth.id OR $auth.admin = true ;.
ACID-транзакция
НАЧАТЬ ТРАНЗАКЦИЮ;.
UPDATE coin:one SET balance += -23.00 ;
UPDATE coin:two SET balance -= 23.00 ;
COMMIT TRANSACTION;.
ИЛИ
ОТМЕНИТЬ ТРАНЗАКЦИЮ;.
Если для таблицы с установленным DROP задана новая транзакция, то все незавершенные транзакции уничтожаются.
Если для таблицы установлен параметр DROP и указана новая транзакция, то все незавершенные транзакции уничтожаются.
По умолчанию новые транзакции доступны только для чтения (если это возможно).
WebSocket
Укажите URL типа ws://dev00:8000/rpc (ws://, wss://).
Передача POST со следующим JSON в качестве тела сообщения.
{
"id": <ID для идентификации>,.
"method": <команда>,.
"params": <массив параметров, требуемых командой>.
}
Аутентификация SurrealDB
Аутентификация ROOT
Пользователь/пароль, указанный при запуске сервера
-pass Отсутствие опции отключает ROOT-аутентификацию
Аутентификация пользователя.
Пользователь/пароль, созданный с помощью DEFINE LOGIN
Токен-аутентификация
Аутентификация с помощью JSON Web Token (JWT) (RFC7519, RFC8725)
Аутентификация по OAuth сторонних производителей
Аутентификация с помощью SCOPE
Предварительно заданные SIGNUP и SIGNIN
Периоды доступа могут быть ограничены
LOGIN
Доступ может быть ограничен NAMESPACE и DATABASE
Пользователи без права доступа к NAMESPACE не могут создавать/удалять БД
DEFINE LOGIN admin ON NAMESPACE PASSWORD "admin.admin";.
DEFINE LOGIN guest ON DATABASE PASSWORD "guest.guest";.
Изображение LOGIN.
surrealdb_login.png
TOKEN.
Разрешить доступ только к запросам с определенным токеном в заголовке
Может быть задан для NAMESPACE, DATABASE и SCOPE
DEFINE TOKEN my_token ON DATABASE
TYPE HS512 VALUE '1234567890';.
SCOPE.
Все поля JSON-RPC задаются переменными
SCOPE предоставляет возможность доступа к базе данных
Доступ к таблицам и полям зависит от PERMISSIONS.
SCOPE с TOKEN не может создавать/модифицировать/удалять таблицы или отображать информацию
DEFINE FIELD email ON TABLE user TYPE string ASSERT is::email($value);
DEFINE INDEX email ON TABLE user COLUMNS email UNIQUE;
DEFINE SCOPE account SESSION 24h
SIGNUP ( CREATE user SET
email = $email, pass = crypto::argon
pass = crypto::argon2::generate($pass) )
SIGNIN ( SELECT * FROM user
WHERE email = $email
AND crypto::argon2::compare(pass, $pass) );.
Изображение SCOPE
surrealdb_scope.png
ПОДПИСКА на аутентификацию SCOPE
let jwt = fetch('https://api.surrealdb.com/signup', {
method: 'POST', {
заголовки: {
'Accept': 'application/json',.
'NS': 'google', // Указываем пространство имен
'DB': 'gmail', // Указываем базу данных
}, }
body: JSON.stringify({
'NS': 'google', // Указываем пространство имен
'SC': 'account',.
email: 'tobie@surrealdb.com',.
pass: 'a85b19*1@jnta0$b&!'
}),.
});
Обращение к токенам и данным аутентификации из запросов.
Для $session, $scope, $token и $auth задается специальная информация, относящаяся к клиенту
При использовании NAMESPACE, DATABASE или TOKEN устанавливаются $session и $token
$toekn устанавливается на все поля JWT-токена
$scope устанавливается в имя SCOPE при аутентификации SCOPE
$auth устанавливается, если JWT имеет поле id в аутентификации SCOPE и данные, указанные в id, существуют в таблице
SELECT * FROM $session;.
SELECT * FROM $token;.
SELECT * FROM $scope;.
SELECT * FROM $auth;.
Живой запрос
Действителен при доступе через WebScoket
Изменения данных передаются в реальном времени клиентам, приложениям, устройствам конечных пользователей и серверу.
Передача данных во внешние библиотеки в реальном времени
Все клиентские устройства синхронизируются.
Чтобы прервать LIVE-запрос, укажите KILL
LIVE SELECT * FROM user WHERE age > 18 ;.
PARALLEL.
PARALLEL добавляется к CREATE, DELETE, UPDATE и SELECT.
Выполнение запроса обрабатывается параллельно
SELECT * FROM test PARALLEL ;
TIMEOUT
TIMEOUT добавляется в CREATE, DELETE, UPDATE и SELECT.
Ожидание в течение времени, указанного при выполнении запроса
SELECT * FROM
http::get('https://ipinfo.io')
TIMEOUT 10s;.
GeoJSON
Pont, Line, Polygon, MultiPoint, MultiLine, MultiPolygon, Collection
UPDATE university:oxford SET area = {
координаты: [
[[ [10.0, 11.2],[10.5, 11.9],[10.8, 12.0],[10.0, 11.2]],]
[[ [9.0, 11.2], [10.5, 11.9],[10.3, 13.0], [9.0, 11.2]]
]
};
SELECT * FROM university:oxford;.
Встроенные функции SurQL
array::xxxx()
combine, complement, concat, difference, disinc, intersect, len, sort::asc, sort::desc, sort, union, all, any, add, append, insert, prepend, remove add, append, insert, prepend, remove, reverse, group, push, pop
count()
crypto::xxxx()
argon2::compare, argon2::generate, bcrypt::compare, bcrypt::generate, md5, pdkdf2::compare, pdkdf2::generate, scrypt::compare, scrypt:: generate, sha1, sha25, sha512
Встроенные функции SurQL (продолжение)
duration::xxxx()
дни, часы, минуты, секунды, недели, годы
geo::xxxx()
площадь, пеленг, центроид, расстояние, hash::decode, hash::encode
http::xxxx()
head, get, put, post, patch, delete
is::xxxx()
alphanum, alpha, domain, email, hexadecimal, latitude, longitude, numeric, semver, url, uuid, url, datetime
Встроенные функции SurQL (продолжение)
math::xxxx()
abs, bottom, ceil, fixed, floor, interquartile, max, mean, midhinge, min, mode, nearestrank, percentile, round, spread, sqrt, stddev, sum, top, trimean, variance, pow
not()
parse::email()
хост, пользователь
parse::url::xxxx)
домен, фрагмент, хост, порт, путь, запрос, схема
Встроенные функции SurQL (продолжение)
rand()
rand::xxxx()
bool, enum, float, guid, int, string, time, uuuid:v4, uuuid:v7, uuid
session::xxxxxx()
db, id, ip, ns, origin, sc, sd, token,.
Встроенные функции SurQL (продолжение)
string::xxxx()
concat, endsWith, join, length, lowercase, repeat, replace, reverse, slice, slug, split, startsWith, trim, uppercase, words
time::xxxx()
day, floor, format, group, hour, minute, month, nano, now, round, second, unix, wday, yday, year, timezone
type::xxxxxx()
bool, datetime, decimal, duration, float, int, number, point, regex, table, thin
Встроенные в SurQL обычные числа
math::xxxx
E, FRAC_1_PI, FRAC_1_SQORT_2, FRAC_2_PI, FRAC_2_SQRT_PI, FRAC_PI_2, FRAC_PI_3, FRAC_PI_4, FRAC_PI_6, FRAC_PI_8, LN_10, LN_2, LOGO10_2, LOG10_E,. LOG2_10, LOG2_E, PI, SQRT_2, TAU
Настройка параметров LET
В качестве переменных могут быть заданы числовые, строковые и другие объекты
На переменную можно ссылаться из запроса как на $variable
LET $test = { some: 'thing', other: true };
SELECT * FROM $test WHERE some = 'thing';
Расширение SurQL с помощью JavaScript
Все значения из SurrealDB автоматически преобразуются в типы JavaScript
Возвращаемые значения из функций JavaScript автоматически преобразуются в значения SurrealDB
Булевы, целые числа, плавающие числа, строки, массивы, объекты и объекты даты
все они автоматически преобразуются в значения SurrealDB или из них.
CREATE user:test SET created_at = function() {
return new Date();
};
Пример JavaScript расширения 1
CREATE platform:test SET version = function() {
const { platform } = await import('os');
return platform();
};
Пример расширения JavaScript 2
LET $value = 'SurrealDB';.
LET $words = ['awesome', 'advanced', 'cool'];
CREATE article:test SET summary = function($value, $words) {
return `${arguments[0]} is ${arguments[1].join(', ')}`;
};
Пример JavaScript расширения 3
CREATE film:test SET
рейтинги = [
{ рейтинг: 6.3 }
{ рейтинг: 8.7 }, }
],.
display = function() {
return this.ratings.filter(r => {
return r.rating >= 7;
}).map(r => {
return { ... .r,.
rating: Math.round(r.rating * 10) }; }
});
};
Простой пример реализации RETful API на языке Python
from urllib.request import Request, urlopen
import base64
import json
from pprint import pprint as pp
_BASE_URL = "http://dev00:8000"
_NAMESPACE = "test"
_DATABASE = "test"
_USER = "root"
_PASS = "root"
auth_str = f"{_USER}:{_PASS}".encode("utf-8")
credential = base64.b64encode(auth_str)
auth = "Basic " + credential.decode("utf-8")
заголовки = {
"Accept": "application/json",.
"Authorization": auth,.
"NS": _NAMESPACE,.
"DB": _DATABASE,.
}
url = _BASE_URL + "/key/human"
request = Request(url, headers=headers)
with urlopen(request) as res:.
data = res.read()
pp(json.loads(data)[0]['result'])
Пример запроса через RETful API на языке Python
импортировать запросы
from requests.auth import HTTPBasicAuth
from pprint import pprint as pp
_URL = "http://dev00:8000/sql"
_NAMESPACE = "test"
_DATABASE = "test"
_USER = "root"
_PASS = "root"
_HEADERS = {
'Content-Type':'application/json',.
'Accept':'application/json',.
'ns': _NAMESPACE,.
'db': _DATABASE'
}
_auth = HTTPBasicAuth(_USER, _PASS)
def db(query):.
res = requests.post( _URL,.
headers=_headers,.
auth = _auth,
data=query )
if "code" in res.json():.
raise Exception(res.json())
return res.json()
if __name__ == '__main__':.
while True:.
sql = input('SQL> ')
if sql.upper() == 'Q':
break
val = db(sql)
pp(val)
Пример запроса через WebSocket в Python
import asyncio
from surrealdb import WebsocketClient
from pprint import pprint as pp
_URL = "ws://dev00:8000/rpc"
_NAMESPACE = "test"
_DATABASE = "test"
_USER = "root"
_PASS = "root"
async def main():.
async с WebsocketClient( url=_URL,.
namespace=_NAMESPACE, database=_DATABASE,.
username=_USER, password=_PASS,.
) as session:.
while True:.
sql = input('SQL> ')
if sql.upper() == 'Q': break
res = await session.query(sql)
pp(res).
Материал PyPI плохо соединяется с WebSocket
Pull-запрос в процессе.
Этот репозиторий пока работает.
GitHub - iisaka51/surrealdb.py at develop
Другие примеры реализации
Flask
GitHub - santiagodonoso/python_flask_surrealdb
FastAPI
GitHub - santiagodonoso/fastapi_surrealdb_v_1
PHP
GitHub - santiagodonoso/php_surrealdb
React
GitHub - rvdende/surrealreact: пользовательский интерфейс проводника SurrealDB, написанный на react.
Deno
https://github.com/officialrajdeepsingh/surrealDb-deno
Typescript.
SurrealDB Explained With Express.js, Node.js, and TypeScript
Следует отметить
Внутренние БД, доступные в surrealdb-1.0.0-beat8
RocksDB, TiKV
FoundationDB, IndexedDB требуют пересборки
IndexedDB может быть использована для встроенных целей
Для доступа к DATABASE требуется NAMESPACE
Различные NAMESPACE приводят к появлению различных DATABASE с одним и тем же именем.
В одной NAMESPACE может быть создано любое количество DATABASE.
Однако для доступа к NAMESPACE/ необходимо разрешение.
Возможно, это ошибка!
Некоторые команды SurQL плохо работают в CLI
Подкоманда SurQL - это доступ к HTTP RestfulAPI с нажатием клавиши возврата
Точки с запятой не распознаются как отдельный запрос
В файлах, переданных подкомандой import, все нормально.
Копирование и вставка выполняется при нажатии клавиши Return.
Комментарии принимаются, но только комментарии являются ошибкой.
Пустой символ ('') считается выполненным.
Переменные, заданные с помощью LET, теряются при нажатии клавиши Return.
Если в середине транзакции нажать клавишу Return, то транзакция будет завершена.
Объявление USE также теряется при нажатии клавиши Return.
Выводы.
Удивительно простая установка и настройка
Очень, очень, очень совместим с веб-приложениями
Мощные запросы, расширяемые с помощью JavaScript
Бизнес-логика и аутентификация пользователей могут обрабатываться непосредственно в базе данных
Упрощенный стек технологий back-end → сокращение времени разработки → снижение затрат
Работа еще не закончена, но очень перспективна
Ссылки
Официальный сайт SurrealDB
GitHub - surrealdb/surrealdb: Масштабируемая, распределенная, совместная, документально-графовая база данных для реального времени в Интернете
StackOverflow
Сбой аутентификации при использовании внешнего JWT-токена в SurrealDB
Траверс отношений вверх в SurrealDB
Как войти в область видимости с помощью SurrealDB?
Как указать пространство имен при использовании веб-сокетов в SurrealDB
Рекомендуемые REST-клиенты
Surrealist
Разделяет результаты нескольких запросов на вкладки.
Отличный пример реализации SurrealDB
GitHub - StarlaneStudios/Surrealist: ⚡ Молниеносная графическая площадка для запросов к SurrealDB для рабочего стола
Tabbed Postman - REST-клиент
Расширение для Chrome
Запросы можно сохранять в виде коллекций
Коллекции можно экспортировать/импортировать
Tabbed Postman - REST-клиент
Клиент Thunder
Расширение для VSCode
Thunder Client - расширение клиента Rest API для VS Code
Приложение.
Параметры сервера и переменные окружения
DB_PATH: место хранения данных (память)
USER Имя пользователя для ROOT-аутентификации (root), --user/-u
PASS Пароль для пользователя ROOT-аутентификации, --pass/-p
ADDR Подсеть, разрешающая ROOT-аутентификацию (127.0.0.1/32), --addr
BIND Имя хоста/IP-адрес для прослушивания соединений (0.0.0.0:8000), --bind/-b
KEY Секретный ключ для ON-DISK шифрования, --key/-k
KVS_CA CA-файл для KVS-соединения, --kvs-ca
KVS_CRT CERT-файл для KVS-соединения, --kvs-crt
KVS_KEY Закрытый ключ для KVS-соединений, --kvs-key
WEB_CRT CERT-файл для прослушивания SSL-соединений, --web-crt
WEB_KEY Закрытый ключ для прослушивания SSL-соединений, --web-key
STRICT Запуск в режиме STRICT, если он установлен, --strict
LOG Уровень журнала "warn", ["info"], "debug", "trace", "full", --log
ACID: четыре характеристики, определяющие транзакцию
Атомарность.
Каждый оператор в транзакции рассматривается как единое целое.
Последовательность.
Гарантирует, что транзакция вносит изменения в таблицу только предопределенным и предсказуемым образом.
Транзакция вносит изменения в таблицу только заранее определенным и предсказуемым образом.
Изоляция
Обеспечивает обработку каждого запроса как независимого, даже если несколько пользователей одновременно читают и записывают данные в одну и ту же таблицу.
Каждый запрос рассматривается так, как будто он возник независимо, даже если несколько пользователей одновременно читают и записывают данные в одну и ту же таблицу.
Долговечность
Гарантирует сохранение изменений данных успешно выполненных транзакций в случае сбоя системы.
Гарантирует сохранение изменений данных успешно выполненных транзакций даже в случае системного сбоя.
Проблема N+1
Проблема, при которой обращение к базе данных приводит к тому, что запросы выполняются в общей сложности N+1 раз.
SELECT выполняется один раз для получения N записей
Выполнение SELECT N раз для получения данных, связанных с N записями.
Склонна к возникновению за кулисами при использовании ORM.
Склонность к тяжелой (медленной) работе приложения
RocksDB
Популярная, высокопроизводительная встроенная база данных KVS.
Форк LevelDB, разработанный компанией Meta (Facebook).
Используется в производстве различными веб-сервисами, такими как Facebook, Yahoo!
Обеспечивает сохранение данных при одновременном повышении производительности и безопасности
Производительность линейно возрастает с увеличением числа процессоров
Производительность RocksDB сильно зависит от настройки платформы
Непростая задача из-за сложности многих настраиваемых параметров
TiKV
База данных KVS, работающая на внутреннем сервере TiDB
Персистентность данных (с RocksDB)
Гарантии целостности данных для распределенных баз данных
MVCC (Multi-Version Concurrency Control)
Реализация распределенных транзакций
Google Parcorator / 2PC (2 Phase Commit)
Сопроцессор
Обратите внимание, что по умолчанию TiKV сконфигурирован как 3-узловой кластер.
Пока кластер не сконфигурирован с 3 узлами, они хранятся во временных файлах.
Временные файлы автоматически удаляются при запуске.
Ссылка: https://docs.pingcap.com/tidb/dev/tikv-configuration-file
Конфигурация кластера: https://tikv.org/docs/5.1/deploy/install/production/
Архитектура TiKV
tikv_stack.png
IndexedDB
Встроенная в браузер база данных KVS
Хранит данные в браузере пользователя.
Позволяет создавать веб-приложения с расширенными возможностями запросов независимо от состояния сети
Без схем
Поддерживает транзакции ACID
Асинхронная обработка
Многоверсионный параллелизм
Пользователи могут удалять данные так же легко, как стирать cookies
Выбор браузера
Данные не могут быть зарегистрированы в IndexedDB, если их емкость превышает определенный уровень.
Объем данных, который может быть зарегистрирован в IndexedDB, зависит от среды.
FoundationDB
NoSQL с поддержкой ACID-транзакций.
Может работать с SQL.
Ключи сортируются.
Производительность 20 000 записей/с на одном ядре при использовании SSD-накопителей
Линейное масштабирование до 500 ядер
Чтение за 1 мс, запись за 5 мс
Возможность распределения/избыточности в кластерной конфигурации
В конфигурацию может быть включен как минимум один узел (без резервирования/добавления узлов в дальнейшем)
Конфигурация FDB по умолчанию работает плохо, поэтому требуется ее настройка
$ fdbcli --exec 'configure ssd'
$ fdbcli --exec 'writemode on'
$ fdbcli --exec 'getrangekeys \x00 \xff'
Ссылка: https://apple.github.io/foundationdb/command-line-interface.html
В бинарных релизах FoundationDB отключена
Зависит от версии FoundationDB, указанной в features
$ cargo feature surreal
Доступные функции для `surreal`.
default = ["storage-rocksdb", "scripting", "http"].
http = ["surrealdb/http"].
scripting = ["surrealdb/scripting"].
storage-fdb = ["surrealdb/kv-fdb-6_3"].
storage-rocksdb = ["surrealdb/kv-rocksdb"]].
storage-tikv = ["surrealdb/kv-tikv"]
$ grep kv-fdb- lib/Cargo.toml
kv-fdb-5_1 = ["foundationdb/fdb-5_1", "kv-fdb"]
kv-fdb-5_2 = ["foundationdb/fdb-5_2", "kv-fdb"].
kv-fdb-6_0 = ["foundationdb/fdb-6_0", "kv-fdb"].
kv-fdb-6_1 = ["foundationdb/fdb-6_1", "kv-fdb"].
kv-fdb-6_2 = ["foundationdb/fdb-6_2", "kv-fdb"].
kv-fdb-6_3 = ["foundationdb/fdb-6_3", "kv-fdb"].
kv-fdb-7_0 = ["foundationdb/fdb-7_0", "kv-fdb"].
kv-fdb-7_1 = ["foundationdb/fdb-7_1", "kv-fdb"].
Доступная нотация является ошибкой в cargo-feature. Выпущены Pull-запросы.
Пересборка SurrealDB.
Настройка среды разработки rust (при необходимости).
$ curl -sSf https://sh.rustup.rs | sh
$ source $HOME/.cargo/env
$ rustup install stable
Клонируйте репозиторий SurrealDB
$ git clone https://github.com/surrealdb/surrealdb.git
$ cd surrealdb
Пересборка.
$ carrgo build -release -all-features # Не работает при 2 ГБ памяти.
# или
$ cargo build -release -features storage-fdb # TiKV будет отключен
TiKV против FoundationDB
Функциональность мониторинга FDB слаба
$ fdbcli --exec 'status json'
TiKV с Prometheus для обращения к данным и Grafana для мониторинга состояния
FDB чувствительна к версиям
FDB по умолчанию хранится в памяти и требует изменения конфигурации
FDB реализована на C++, TiKV - на Rust
FDB может обслуживаться как минимум одним узлом, TiKV требует не менее трех узлов
Репликация RocksDB
Репликация в реальном времени возможна с помощью rocksplicator
https://github.com/pinterest/rocksplicator
Заметим, однако, что Rocksplicator - это архивный проект, который активно не поддерживается компанией Pinterest.
О хранении бинарных файлов.
SurrealDB не предназначена для такого использования.
Следует рассмотреть возможность использования объектного хранилища
GitHub - minio/minio: мультиоблачное хранилище объектов
GitHub - scality/Zenko: Zenko - мультиоблачный контроллер данных с открытым исходным кодом: владейте и контролируйте свои данные в любом облаке.
Синтаксис SurQL
INFO
INFO FOR [
KV
| NS | NAMESPACE
| DATABASE
| DATABASE
| TABLE @table
];
DEFINE NAMESPACE | DATABASE ...
DEFINE [
NAMESPACE @name
DEFINE [ NAMESPACE | DATABASE @name
| LOGIN @name ON [ NAMESPACE | DATABASE ]
[ PASSWORD @pass | PASSHASH @hash ]
| TOKEN @name ON [ NAMESPACE | DATABASE | SCOPE ]
TYPE @algorithm VALUE @value
| SCOPE @name [ SESSION @duration ]
[ SIGNUP @expression ] [ SIGNIN @expression ]
| EVENT @name ON [ TABLE ] @table
WHEN @expression THEN @expression
@алгоритм
EDDSA, ES256, ES384, ES512, HS256, HS384, HS512,.
PS256, PS384, PS512, RS256, RS384, RS51
ОПРЕДЕЛЕНИЕ ТАБЛИЦЫ
DEFINE [
| TABLE @name
[DROP]
[ SCHEMAFULL | SCHEMALESS ]
[ AS SELECT @projections
FROM @tables
[ WHERE @condition ]
[ GROUP [ BY ] @groups ]
]
[ PERMISSIONS [ NONE | FULL
| FOR select @expression
| FOR create @expression
| FOR update @expression
| FOR delete @expression
] ]
; ;
ОПРЕДЕЛЕНИЕ ПОЛЯ | ИНДЕКСА
ОПРЕДЕЛИТЬ [
| FIELD @name ON [ TABLE ] @table
[ TYPE @type ]
[ VALUE @expression ]
[ ASSERT @expression ]
[ PERMISSIONS [ NONE | FULL
| FOR select @expression
| FOR create @expression
| FOR update @expression
| FOR delete @expression
]
| INDEX @name ON [ TABLE ] @table [ FIELDS | COLUMNS ] @fields [ UNIQUE ]
] ;
CREATE
CREATE @targets
[ CONTENT @value
| SET @field = @value ...
]
[ RETURN [ NONE | BEFORE | AFTER | DIFF | @projections ... ]
[ TIMEOUT @duration ]
[ PARALLEL ]
;
УДАЛИТЬ
УДАЛЕНИЕ [
NAMESPACE @name
| DATABASE @name
| LOGIN @name ON [ NAMESPACE | DATABASE ]
| TOKEN @name ON [ NAMESPACE | DATABASE ]
| SCOPE @name
| ТАБЛИЦА @name
| TABLE @name
| FIELD @name ON [ TABLE ] @table
| INDEX @name ON [ TABLE ] @table
] ;
INSERT
INSERT [ IGNORE ] INTO @what
[ @value
| (@fields) VALUES (@values)
[ ON DUPLICATE KEY UPDATE @field = @value ... ]
]
;
UPDATE
UPDATE @targets.
[ CONTENT @value
| MERGE @value
| PATCH @value
| SET @field = @value ...
]
[ WHERE @condition ]
[ RETURN [ NONE | BEFORE | AFTER | DIFF | @projections ... ]
[ TIMEOUT @duration ]
[ PARALLEL ]
;
DELETE
DELETE @targets ]
[ WHERE @condition ]
[ RETURN [ NONE | BEFORE | AFTER | DIFF | @projections ... ]
[ TIMEOUT @duration ]
[ PARALLEL ]
;
SELECT
SELECT @projections
FROM @targets
[ WHERE @condition ]
[ SPLIT [ AT ] @field ... ]
[ GROUP [ BY ] @field ... ]
[ ORDER [ BY ]
@field [RAND()| COLLATE| NUMERIC ] [ ASC | DESC ] ...
]
[ LIMIT [ BY ] @limit ]
[ START [ AT ] @start ]
[ FETCH @field ... ]
[ TIMEOUT @duration ]
[ PARALLEL ]
;
USE
USE.
[ NAMESPACE | NS ] @namespace ]
[[ DATABASE | DB ] @database ] ;
поделиться
Зарегистрируйтесь сейчас и начните использовать Qiita с большим удобством!
Мы будем присылать вам статьи, которые соответствуют вашим потребностям.
В дальнейшем вы сможете эффективно перечитывать полезную информацию.
О функциях, которые можно использовать при входе в систему
iisaka51
@iisaka51(Гоити (Иисака) Юкава)
https://github.com/iisaka51
ссылка
rss
0 件のコメント:
コメントを投稿