Перейти к основному содержимому

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 типизирован, валидируется, имеет стандартный формат