UUID
Поле типа UUID (Universally Unique Identifier) используется для хранения универсальных уникальных идентификаторов.
Основные характеристики
- Тип данных: 128-битный идентификатор
- Формат: 36-символьная строка (8-4-4-4-12)
- Уникальность: Практически гарантированная глобальная уникальность
- Версии: UUID v1, v4, v5 (наиболее популярна v4)
- Автогенерация: Автоматически генерируется при создании
Формат UUID
Стандартный формат: 550e8400-e29b-41d4-a716-446655440000
Состоит из 5 групп шестнадцатеричных цифр, разделенных дефисами:
- 8 символов
- 4 символа
- 4 символа
- 4 символа
- 12 символов
Версии UUID
UUID v1 (на основе времени и MAC-адреса)
// Содержит временную метку и MAC-адрес
// Пример: 6ba7b810-9dad-11d1-80b4-00c04fd430c8
UUID v4 (случайный)
// Полностью случайный (наиболее популярный)
// Пример: 550e8400-e29b-41d4-a716-446655440000
UUID v5 (на основе имени и пространства имен)
// Генерируется из имени и namespace
// Детерминированный (одинаковый вход = одинаковый UUID)
Настройки поля
При создании поля типа "UUID" доступны следующие настройки:
- Название поля: Отображаемое имя поля
- Системное имя: Уникальный идентификатор для API
- Описание: Подсказка для пользователей
- Версия UUID: v1, v4 или v5
- Автогенерация: Автоматически генерировать при создании
- Уникальность: Всегда уникальный
Примеры использования
Публичный идентификатор
{
"name": "public_id",
"type": "uuid",
"version": "v4",
"auto": true,
"unique": true
}
ID сессии
{
"name": "session_id",
"type": "uuid",
"version": "v4",
"auto": true
}
Токен
{
"name": "api_token",
"type": "uuid",
"version": "v4"
}
Работа через API
Автоматическая генерация
const record = await emd.database.collection('users').create({
name: 'Иван Иванов'
// public_id будет сгенерирован автоматически
});
console.log(record.public_id); // "550e8400-e29b-41d4-a716-446655440000"
Создание с явным UUID
import { v4 as uuidv4 } from 'uuid';
const customUuid = uuidv4();
const record = await emd.database.collection('users').create({
public_id: customUuid,
name: 'Иван Иванов'
});
Поиск по UUID
const record = await emd.database.collection('users').findOne({
public_id: '550e8400-e29b-41d4-a716-446655440000'
});
Генерация UUID
UUID v4 (случайный)
import { v4 as uuidv4 } from 'uuid';
const uuid = uuidv4();
// "550e8400-e29b-41d4-a716-446655440000"
UUID v1 (на основе времени)
import { v1 as uuidv1 } from 'uuid';
const uuid = uuidv1();
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
UUID v5 (на основе имени)
import { v5 as uuidv5 } from 'uuid';
const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341';
const uuid = uuidv5('user@example.com', MY_NAMESPACE);
// Всегда один и тот же UUID для одного email
Валидация UUID
Проверка корректности
import { validate as uuidValidate, version as uuidVersion } from 'uuid';
function isValidUUID(uuid) {
return uuidValidate(uuid);
}
console.log(isValidUUID('550e8400-e29b-41d4-a716-446655440000')); // true
console.log(isValidUUID('invalid-uuid')); // false
Проверка версии
import { version as uuidVersion } from 'uuid';
const uuid = '550e8400-e29b-41d4-a716-446655440000';
console.log(uuidVersion(uuid)); // 4
Валидация при создании
try {
await emd.database.collection('users').create({
public_id: 'invalid-uuid'
});
} catch (error) {
console.error(error.message); // "Invalid UUID"
}
Использование в URL
Публичные ссылки
const record = await emd.database.collection('articles').create({
title: 'Моя статья'
// public_id генерируется автоматически
});
const publicUrl = `https://example.com/articles/${record.public_id}`;
// https://example.com/articles/550e8400-e29b-41d4-a716-446655440000
Короткие ссылки
// Использовать только первые 8 символов для коротких URL
const shortId = record.public_id.split('-')[0];
const shortUrl = `https://example.com/a/${shortId}`;
// https://example.com/a/550e8400
Использование в API
API ключи
import { v4 as uuidv4 } from 'uuid';
const apiKey = await emd.database.collection('api_keys').create({
userId: currentUserId,
key: uuidv4(),
name: 'Production API Key',
created_at: new Date()
});
console.log(`Your API key: ${apiKey.key}`);
Токены доступа
const accessToken = uuidv4();
const refreshToken = uuidv4();
await emd.database.collection('tokens').create({
userId: currentUserId,
access_token: accessToken,
refresh_token: refreshToken,
expires_at: new Date(Date.now() + 3600000) // 1 час
});
Поиск и фильтрация
Поиск по списку UUID
const uuids = [
'550e8400-e29b-41d4-a716-446655440000',
'6ba7b810-9dad-11d1-80b4-00c04fd430c8'
];
const records = await emd.database.collection('users').find({
public_id: { $in: uuids }
});
Проверка существования
const exists = await emd.database.collection('users').exists({
public_id: '550e8400-e29b-41d4-a716-446655440000'
});
Преобразование форматов
UUID без дефисов
const uuid = '550e8400-e29b-41d4-a716-446655440000';
const compactUuid = uuid.replace(/-/g, '');
// "550e8400e29b41d4a716446655440000"
Восстановление формата
function formatUUID(compactUuid) {
return compactUuid.replace(
/^(.{8})(.{4})(.{4})(.{4})(.{12})$/,
'$1-$2-$3-$4-$5'
);
}
const formatted = formatUUID('550e8400e29b41d4a716446655440000');
// "550e8400-e29b-41d4-a716-446655440000"
UUID в Base64
function uuidToBase64(uuid) {
const hex = uuid.replace(/-/g, '');
const buffer = Buffer.from(hex, 'hex');
return buffer.toString('base64');
}
const base64 = uuidToBase64('550e8400-e29b-41d4-a716-446655440000');
// Более короткая форма для URL
Индексация
// Создать индекс для быстрого поиска
await emd.database.collection('users').createIndex({
public_id: 1
}, {
unique: true
});
Производительность
Преимущества UUID
- Глобальная уникальность (можно генерировать на клиенте)
- Не раскрывает информацию о количестве записей
- Подходит для распределенных систем
- Безопасен для публичных URL
Недостатки UUID
- Больший размер (16 байт vs 4-8 байт для integer)
- Хуже индексируется (случайный порядок)
- Менее читаем для человека
Типичные сценарии использования
Публичные идентификаторы
// Вместо /users/123 используйте /users/550e8400-...
const user = await emd.database.collection('users').findOne({
public_id: req.params.id
});
Токены сброса пароля
import { v4 as uuidv4 } from 'uuid';
const resetToken = uuidv4();
await emd.database.collection('password_resets').create({
userId: user._id,
token: resetToken,
expires_at: new Date(Date.now() + 3600000) // 1 час
});
// Отправить email с ссылкой
const resetUrl = `https://example.com/reset-password?token=${resetToken}`;
Идентификаторы файлов
import { v4 as uuidv4 } from 'uuid';
const fileId = uuidv4();
const fileName = `${fileId}.jpg`;
await storage.upload(file, fileName);
Безопасность
Непредсказуемость
UUID v4 полностью случайный, что делает его безопасным для публичных идентификаторов.
Защита от перебора
В отличие от auto-increment ID, UUID невозможно перебрать.
Конфиденциальность
UUID не раскрывает информацию о количестве записей или времени создания.
Рекомендации
- Используйте UUID v4 для публичных идентификаторов
- Используйте UUID для API ключей и токенов
- Для внутренних ссылок между записями используйте ObjectId (эффективнее)
- Создавайте уникальный индекс для UUID полей
- Для коротких URL используйте первые 8 символов (с проверкой уникальности)
- Не используйте UUID v1 (раскрывает MAC-адрес)
- Валидируйте UUID перед использованием
Отличие от других типов
- UUID vs ObjectId: UUID больше (16 vs 12 байт), но более стандартизирован
- UUID vs Auto-increment: UUID не раскрывает количество записей, работает в распределенных системах
- UUID vs String: UUID типизирован, валидируется, имеет стандартный формат